diff options
Diffstat (limited to 'spec/requests')
62 files changed, 1303 insertions, 845 deletions
diff --git a/spec/requests/api/access_requests_spec.rb b/spec/requests/api/access_requests_spec.rb index c8eacb38e6f..6bd17697c33 100644 --- a/spec/requests/api/access_requests_spec.rb +++ b/spec/requests/api/access_requests_spec.rb @@ -7,7 +7,7 @@ describe API::AccessRequests do let(:stranger) { create(:user) } let(:project) do - create(:empty_project, :public, :access_requestable, creator_id: master.id, namespace: master.namespace) do |project| + create(:project, :public, :access_requestable, creator_id: master.id, namespace: master.namespace) do |project| project.team << [developer, :developer] project.team << [master, :master] project.request_access(access_requester) diff --git a/spec/requests/api/award_emoji_spec.rb b/spec/requests/api/award_emoji_spec.rb index 6d822b5cb4f..1dd9f3f6ddc 100644 --- a/spec/requests/api/award_emoji_spec.rb +++ b/spec/requests/api/award_emoji_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe API::AwardEmoji do let(:user) { create(:user) } - let!(:project) { create(:empty_project) } + let!(:project) { create(:project) } let(:issue) { create(:issue, project: project) } let!(:award_emoji) { create(:award_emoji, awardable: issue, user: user) } let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) } diff --git a/spec/requests/api/boards_spec.rb b/spec/requests/api/boards_spec.rb index c27db716ef8..43b381c2219 100644 --- a/spec/requests/api/boards_spec.rb +++ b/spec/requests/api/boards_spec.rb @@ -6,7 +6,7 @@ describe API::Boards do let(:non_member) { create(:user) } let(:guest) { create(:user) } let(:admin) { create(:user, :admin) } - let!(:project) { create(:empty_project, :public, creator_id: user.id, namespace: user.namespace ) } + let!(:project) { create(:project, :public, creator_id: user.id, namespace: user.namespace ) } let!(:dev_label) do create(:label, title: 'Development', color: '#FFAABB', project: project) @@ -188,7 +188,7 @@ describe API::Boards do context "when the user is project owner" do let(:owner) { create(:user) } - let(:project) { create(:empty_project, namespace: owner.namespace) } + let(:project) { create(:project, namespace: owner.namespace) } it "deletes the list if an admin requests it" do delete api("#{base_url}/#{dev_list.id}", owner) diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb index c64499fc8c0..5a2e1b2cf2d 100644 --- a/spec/requests/api/branches_spec.rb +++ b/spec/requests/api/branches_spec.rb @@ -1,25 +1,31 @@ require 'spec_helper' -require 'mime/types' describe API::Branches do let(:user) { create(:user) } - let!(:project) { create(:project, :repository, creator: user) } - let!(:master) { create(:project_member, :master, user: user, project: project) } - let(:guest) { create(:user).tap { |u| create(:project_member, :guest, user: u, project: project) } } - let!(:branch_name) { 'feature' } - let!(:branch_sha) { '0b4bc9a49b562e85de7cc9e834518ea6828729b9' } - let(:branch_with_dot) { CreateBranchService.new(project, user).execute("with.1.2.3", "master")[:branch] } + let(:guest) { create(:user).tap { |u| project.add_guest(u) } } + let(:project) { create(:project, :repository, creator: user, path: 'my.project') } + let(:branch_name) { 'feature' } + let(:branch_sha) { '0b4bc9a49b562e85de7cc9e834518ea6828729b9' } + let(:branch_with_dot) { project.repository.find_branch('ends-with.json') } + let(:branch_with_slash) { project.repository.find_branch('improve/awesome') } + + let(:project_id) { project.id } + let(:current_user) { nil } + + before do + project.add_master(user) + end describe "GET /projects/:id/repository/branches" do - let(:route) { "/projects/#{project.id}/repository/branches" } + let(:route) { "/projects/#{project_id}/repository/branches" } shared_examples_for 'repository branches' do it 'returns the repository branches' do get api(route, current_user), per_page: 100 - expect(response).to have_http_status(200) + expect(response).to have_gitlab_http_status(200) + expect(response).to match_response_schema('public_api/v4/branches') expect(response).to include_pagination_headers - 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 @@ -34,10 +40,9 @@ describe API::Branches do end context 'when unauthenticated', 'and project is public' do - it_behaves_like 'repository branches' do - let(:project) { create(:project, :public, :repository) } - let(:current_user) { nil } - end + let(:project) { create(:project, :public, :repository) } + + it_behaves_like 'repository branches' end context 'when unauthenticated', 'and project is private' do @@ -47,9 +52,15 @@ describe API::Branches do end end - context 'when authenticated', 'as a developer' do - it_behaves_like 'repository branches' do - let(:current_user) { user } + context 'when authenticated', 'as a master' do + let(:current_user) { user } + + it_behaves_like 'repository branches' + + context 'requesting with the escaped project full path' do + let(:project_id) { CGI.escape(project.full_path) } + + it_behaves_like 'repository branches' end end @@ -61,31 +72,15 @@ describe API::Branches do end describe "GET /projects/:id/repository/branches/:branch" do - let(:route) { "/projects/#{project.id}/repository/branches/#{branch_name}" } + let(:route) { "/projects/#{project_id}/repository/branches/#{branch_name}" } - shared_examples_for 'repository branch' do |merged: false| + shared_examples_for 'repository branch' do it 'returns the repository branch' do get api(route, current_user) - expect(response).to have_http_status(200) - expect(json_response['name']).to eq(branch_name) - expect(json_response['merged']).to eq(merged) - expect(json_response['protected']).to eq(false) - expect(json_response['developers_can_push']).to eq(false) - expect(json_response['developers_can_merge']).to eq(false) - - json_commit = json_response['commit'] - expect(json_commit['id']).to eq(branch_sha) - expect(json_commit).to have_key('short_id') - expect(json_commit).to have_key('title') - expect(json_commit).to have_key('message') - expect(json_commit).to have_key('author_name') - expect(json_commit).to have_key('author_email') - expect(json_commit).to have_key('authored_date') - expect(json_commit).to have_key('committer_name') - expect(json_commit).to have_key('committer_email') - expect(json_commit).to have_key('committed_date') - expect(json_commit).to have_key('parent_ids') + expect(response).to have_gitlab_http_status(200) + expect(response).to match_response_schema('public_api/v4/branch') + expect(json_response['name']).to eq(CGI.unescape(branch_name)) end context 'when branch does not exist' do @@ -107,10 +102,9 @@ describe API::Branches do end context 'when unauthenticated', 'and project is public' do - it_behaves_like 'repository branch' do - let(:project) { create(:project, :public, :repository) } - let(:current_user) { nil } - end + let(:project) { create(:project, :public, :repository) } + + it_behaves_like 'repository branch' end context 'when unauthenticated', 'and project is private' do @@ -120,22 +114,41 @@ describe API::Branches do end end - context 'when authenticated', 'as a developer' do + context 'when authenticated', 'as a master' do let(:current_user) { user } + it_behaves_like 'repository branch' context 'when branch contains a dot' do let(:branch_name) { branch_with_dot.name } - let(:branch_sha) { project.commit('master').sha } it_behaves_like 'repository branch' end - context 'when branch is merged' do - let(:branch_name) { 'merge-test' } - let(:branch_sha) { project.commit('merge-test').sha } + context 'when branch contains a slash' do + let(:branch_name) { branch_with_slash.name } + + it_behaves_like '404 response' do + let(:request) { get api(route, current_user) } + end + end + + context 'when branch contains an escaped slash' do + let(:branch_name) { CGI.escape(branch_with_slash.name) } + + it_behaves_like 'repository branch' + end + + context 'requesting with the escaped project full path' do + let(:project_id) { CGI.escape(project.full_path) } + + it_behaves_like 'repository branch' - it_behaves_like 'repository branch', merged: true + context 'when branch contains a dot' do + let(:branch_name) { branch_with_dot.name } + + it_behaves_like 'repository branch' + end end end @@ -147,268 +160,348 @@ describe API::Branches do end describe 'PUT /projects/:id/repository/branches/:branch/protect' do - context "when a protected branch doesn't already exist" do - it 'protects a single branch' do - put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user) + let(:route) { "/projects/#{project_id}/repository/branches/#{branch_name}/protect" } - expect(response).to have_http_status(200) - expect(json_response['name']).to eq(branch_name) - expect(json_response['commit']['id']).to eq(branch_sha) - expect(json_response['protected']).to eq(true) - expect(json_response['developers_can_push']).to eq(false) - expect(json_response['developers_can_merge']).to eq(false) - end - - it "protects a single branch with dots in the name" do - put api("/projects/#{project.id}/repository/branches/#{branch_with_dot.name}/protect", user) + shared_examples_for 'repository new protected branch' do + it 'protects a single branch' do + put api(route, current_user) - expect(response).to have_http_status(200) - expect(json_response['name']).to eq(branch_with_dot.name) + expect(response).to have_gitlab_http_status(200) + expect(response).to match_response_schema('public_api/v4/branch') + expect(json_response['name']).to eq(CGI.unescape(branch_name)) expect(json_response['protected']).to eq(true) end it 'protects a single branch and developers can push' do - put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user), - developers_can_push: true + put api(route, current_user), developers_can_push: true - expect(response).to have_http_status(200) - expect(json_response['name']).to eq(branch_name) - expect(json_response['commit']['id']).to eq(branch_sha) + expect(response).to have_gitlab_http_status(200) + expect(response).to match_response_schema('public_api/v4/branch') + expect(json_response['name']).to eq(CGI.unescape(branch_name)) expect(json_response['protected']).to eq(true) expect(json_response['developers_can_push']).to eq(true) expect(json_response['developers_can_merge']).to eq(false) end it 'protects a single branch and developers can merge' do - put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user), - developers_can_merge: true + put api(route, current_user), developers_can_merge: true - expect(response).to have_http_status(200) - expect(json_response['name']).to eq(branch_name) - expect(json_response['commit']['id']).to eq(branch_sha) + expect(response).to have_gitlab_http_status(200) + expect(response).to match_response_schema('public_api/v4/branch') + expect(json_response['name']).to eq(CGI.unescape(branch_name)) expect(json_response['protected']).to eq(true) expect(json_response['developers_can_push']).to eq(false) expect(json_response['developers_can_merge']).to eq(true) end it 'protects a single branch and developers can push and merge' do - put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user), - developers_can_push: true, developers_can_merge: true + put api(route, current_user), developers_can_push: true, developers_can_merge: true - expect(response).to have_http_status(200) - expect(json_response['name']).to eq(branch_name) - expect(json_response['commit']['id']).to eq(branch_sha) + expect(response).to have_gitlab_http_status(200) + expect(response).to match_response_schema('public_api/v4/branch') + expect(json_response['name']).to eq(CGI.unescape(branch_name)) expect(json_response['protected']).to eq(true) expect(json_response['developers_can_push']).to eq(true) expect(json_response['developers_can_merge']).to eq(true) end + + context 'when branch does not exist' do + let(:branch_name) { 'unknown' } + + it_behaves_like '404 response' do + let(:request) { put api(route, current_user) } + let(:message) { '404 Branch Not Found' } + end + end + + context 'when repository is disabled' do + include_context 'disabled repository' + + it_behaves_like '403 response' do + let(:request) { put api(route, current_user) } + end + end end - context 'for an existing protected branch' do - before do - project.repository.add_branch(user, protected_branch.name, 'master') + context 'when unauthenticated', 'and project is private' do + it_behaves_like '404 response' do + let(:request) { put api(route) } + let(:message) { '404 Project Not Found' } end + end + + context 'when authenticated', 'as a guest' do + it_behaves_like '403 response' do + let(:request) { put api(route, guest) } + end + end + + context 'when authenticated', 'as a master' do + let(:current_user) { user } - context "when developers can push and merge" do - let(:protected_branch) { create(:protected_branch, :developers_can_push, :developers_can_merge, project: project, name: 'protected_branch') } + context "when a protected branch doesn't already exist" do + it_behaves_like 'repository new protected branch' - it 'updates that a developer cannot push or merge' do - put api("/projects/#{project.id}/repository/branches/#{protected_branch.name}/protect", user), - developers_can_push: false, developers_can_merge: false + context 'when branch contains a dot' do + let(:branch_name) { branch_with_dot.name } - expect(response).to have_http_status(200) - expect(json_response['name']).to eq(protected_branch.name) - expect(json_response['protected']).to eq(true) - expect(json_response['developers_can_push']).to eq(false) - expect(json_response['developers_can_merge']).to eq(false) + it_behaves_like 'repository new protected branch' end - it "doesn't result in 0 access levels when 'developers_can_push' is switched off" do - put api("/projects/#{project.id}/repository/branches/#{protected_branch.name}/protect", user), - developers_can_push: false + context 'when branch contains a slash' do + let(:branch_name) { branch_with_slash.name } - expect(response).to have_http_status(200) - expect(json_response['name']).to eq(protected_branch.name) - expect(protected_branch.reload.push_access_levels.first).to be_present - expect(protected_branch.reload.push_access_levels.first.access_level).to eq(Gitlab::Access::MASTER) + it_behaves_like '404 response' do + let(:request) { put api(route, current_user) } + end end - it "doesn't result in 0 access levels when 'developers_can_merge' is switched off" do - put api("/projects/#{project.id}/repository/branches/#{protected_branch.name}/protect", user), - developers_can_merge: false + context 'when branch contains an escaped slash' do + let(:branch_name) { CGI.escape(branch_with_slash.name) } - expect(response).to have_http_status(200) - expect(json_response['name']).to eq(protected_branch.name) - expect(protected_branch.reload.merge_access_levels.first).to be_present - expect(protected_branch.reload.merge_access_levels.first.access_level).to eq(Gitlab::Access::MASTER) + it_behaves_like 'repository new protected branch' + end + + context 'requesting with the escaped project full path' do + let(:project_id) { CGI.escape(project.full_path) } + + it_behaves_like 'repository new protected branch' + + context 'when branch contains a dot' do + let(:branch_name) { branch_with_dot.name } + + it_behaves_like 'repository new protected branch' + end end end - context "when developers cannot push or merge" do - let(:protected_branch) { create(:protected_branch, project: project, name: 'protected_branch') } + context 'when protected branch already exists' do + before do + project.repository.add_branch(user, protected_branch.name, 'master') + end + + context 'when developers can push and merge' do + let(:protected_branch) { create(:protected_branch, :developers_can_push, :developers_can_merge, project: project, name: 'protected_branch') } + + it 'updates that a developer cannot push or merge' do + put api("/projects/#{project.id}/repository/branches/#{protected_branch.name}/protect", user), + developers_can_push: false, developers_can_merge: false + + expect(response).to have_gitlab_http_status(200) + expect(response).to match_response_schema('public_api/v4/branch') + expect(json_response['name']).to eq(protected_branch.name) + expect(json_response['protected']).to eq(true) + expect(json_response['developers_can_push']).to eq(false) + expect(json_response['developers_can_merge']).to eq(false) + expect(protected_branch.reload.push_access_levels.first.access_level).to eq(Gitlab::Access::MASTER) + expect(protected_branch.reload.merge_access_levels.first.access_level).to eq(Gitlab::Access::MASTER) + end + end + + context 'when developers cannot push or merge' do + let(:protected_branch) { create(:protected_branch, project: project, name: 'protected_branch') } - it 'updates that a developer can push and merge' do - put api("/projects/#{project.id}/repository/branches/#{protected_branch.name}/protect", user), - developers_can_push: true, developers_can_merge: true + it 'updates that a developer can push and merge' do + put api("/projects/#{project.id}/repository/branches/#{protected_branch.name}/protect", user), + developers_can_push: true, developers_can_merge: true - expect(response).to have_http_status(200) - expect(json_response['name']).to eq(protected_branch.name) - expect(json_response['protected']).to eq(true) - expect(json_response['developers_can_push']).to eq(true) - expect(json_response['developers_can_merge']).to eq(true) + expect(response).to have_gitlab_http_status(200) + expect(response).to match_response_schema('public_api/v4/branch') + expect(json_response['name']).to eq(protected_branch.name) + expect(json_response['protected']).to eq(true) + expect(json_response['developers_can_push']).to eq(true) + expect(json_response['developers_can_merge']).to eq(true) + end end end end + end - context "multiple API calls" do - it "returns success when `protect` is called twice" do - put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user) - put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user) + describe 'PUT /projects/:id/repository/branches/:branch/unprotect' do + let(:route) { "/projects/#{project_id}/repository/branches/#{branch_name}/unprotect" } - expect(response).to have_http_status(200) - expect(json_response['name']).to eq(branch_name) - expect(json_response['protected']).to eq(true) - expect(json_response['developers_can_push']).to eq(false) - expect(json_response['developers_can_merge']).to eq(false) + shared_examples_for 'repository unprotected branch' do + it 'unprotects a single branch' do + put api(route, current_user) + + expect(response).to have_gitlab_http_status(200) + expect(response).to match_response_schema('public_api/v4/branch') + expect(json_response['name']).to eq(CGI.unescape(branch_name)) + expect(json_response['protected']).to eq(false) end - it "returns success when `protect` is called twice with `developers_can_push` turned on" do - put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user), developers_can_push: true - put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user), developers_can_push: true + context 'when branch does not exist' do + let(:branch_name) { 'unknown' } - expect(response).to have_http_status(200) - expect(json_response['name']).to eq(branch_name) - expect(json_response['protected']).to eq(true) - expect(json_response['developers_can_push']).to eq(true) - expect(json_response['developers_can_merge']).to eq(false) + it_behaves_like '404 response' do + let(:request) { put api(route, current_user) } + let(:message) { '404 Branch Not Found' } + end end - it "returns success when `protect` is called twice with `developers_can_merge` turned on" do - put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user), developers_can_merge: true - put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user), developers_can_merge: true + context 'when repository is disabled' do + include_context 'disabled repository' - expect(response).to have_http_status(200) - expect(json_response['name']).to eq(branch_name) - expect(json_response['protected']).to eq(true) - expect(json_response['developers_can_push']).to eq(false) - expect(json_response['developers_can_merge']).to eq(true) + it_behaves_like '403 response' do + let(:request) { put api(route, current_user) } + end end end - it "returns a 404 error if branch not found" do - put api("/projects/#{project.id}/repository/branches/unknown/protect", user) - expect(response).to have_http_status(404) + context 'when unauthenticated', 'and project is private' do + it_behaves_like '404 response' do + let(:request) { put api(route) } + let(:message) { '404 Project Not Found' } + end end - it "returns a 403 error if guest" do - put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", guest) - expect(response).to have_http_status(403) + context 'when authenticated', 'as a guest' do + it_behaves_like '403 response' do + let(:request) { put api(route, guest) } + end end - end - describe "PUT /projects/:id/repository/branches/:branch/unprotect" do - it "unprotects a single branch" do - put api("/projects/#{project.id}/repository/branches/#{branch_name}/unprotect", user) - expect(response).to have_http_status(200) + context 'when authenticated', 'as a master' do + let(:current_user) { user } + + context "when a protected branch doesn't already exist" do + it_behaves_like 'repository unprotected branch' + + context 'when branch contains a dot' do + let(:branch_name) { branch_with_dot.name } + + it_behaves_like 'repository unprotected branch' + end + + context 'when branch contains a slash' do + let(:branch_name) { branch_with_slash.name } + + it_behaves_like '404 response' do + let(:request) { put api(route, current_user) } + end + end + + context 'when branch contains an escaped slash' do + let(:branch_name) { CGI.escape(branch_with_slash.name) } - expect(json_response['name']).to eq(branch_name) - expect(json_response['commit']['id']).to eq(branch_sha) - expect(json_response['protected']).to eq(false) + it_behaves_like 'repository unprotected branch' + end + + context 'requesting with the escaped project full path' do + let(:project_id) { CGI.escape(project.full_path) } + + it_behaves_like 'repository unprotected branch' + + context 'when branch contains a dot' do + let(:branch_name) { branch_with_dot.name } + + it_behaves_like 'repository unprotected branch' + end + end + end end + end - it "update branches with dots in branch name" do - put api("/projects/#{project.id}/repository/branches/#{branch_with_dot.name}/unprotect", user) + describe 'POST /projects/:id/repository/branches' do + let(:route) { "/projects/#{project_id}/repository/branches" } - expect(response).to have_http_status(200) - expect(json_response['name']).to eq(branch_with_dot.name) - expect(json_response['protected']).to eq(false) + shared_examples_for 'repository new branch' do + it 'creates a new branch' do + post api(route, current_user), branch: 'feature1', ref: branch_sha + + expect(response).to have_gitlab_http_status(201) + expect(response).to match_response_schema('public_api/v4/branch') + expect(json_response['name']).to eq('feature1') + expect(json_response['commit']['id']).to eq(branch_sha) + end + + context 'when repository is disabled' do + include_context 'disabled repository' + + it_behaves_like '403 response' do + let(:request) { post api(route, current_user) } + end + end end - it "returns success when unprotect branch" do - put api("/projects/#{project.id}/repository/branches/unknown/unprotect", user) - expect(response).to have_http_status(404) + context 'when unauthenticated', 'and project is private' do + it_behaves_like '404 response' do + let(:request) { post api(route) } + let(:message) { '404 Project Not Found' } + end end - it "returns success when unprotect branch again" do - put api("/projects/#{project.id}/repository/branches/#{branch_name}/unprotect", user) - put api("/projects/#{project.id}/repository/branches/#{branch_name}/unprotect", user) - expect(response).to have_http_status(200) + context 'when authenticated', 'as a guest' do + it_behaves_like '403 response' do + let(:request) { post api(route, guest) } + end end - end - describe "POST /projects/:id/repository/branches" do - it "creates a new branch" do - post api("/projects/#{project.id}/repository/branches", user), - branch: 'feature1', - ref: branch_sha + context 'when authenticated', 'as a master' do + let(:current_user) { user } - expect(response).to have_http_status(201) + context "when a protected branch doesn't already exist" do + it_behaves_like 'repository new branch' - expect(json_response['name']).to eq('feature1') - expect(json_response['commit']['id']).to eq(branch_sha) - end + context 'requesting with the escaped project full path' do + let(:project_id) { CGI.escape(project.full_path) } - it "denies for user without push access" do - post api("/projects/#{project.id}/repository/branches", guest), - branch: branch_name, - ref: branch_sha - expect(response).to have_http_status(403) + it_behaves_like 'repository new branch' + end + end end it 'returns 400 if branch name is invalid' do - post api("/projects/#{project.id}/repository/branches", user), - branch: 'new design', - ref: branch_sha - expect(response).to have_http_status(400) + post api(route, user), branch: '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 api("/projects/#{project.id}/repository/branches", user), - branch: 'new_design1', - ref: branch_sha - expect(response).to have_http_status(201) - - post api("/projects/#{project.id}/repository/branches", user), - branch: 'new_design1', - ref: branch_sha - expect(response).to have_http_status(400) + post api(route, user), branch: 'new_design1', ref: branch_sha + + expect(response).to have_gitlab_http_status(201) + + post api(route, user), branch: '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 api("/projects/#{project.id}/repository/branches", user), - branch: 'new_design3', - ref: 'foo' - expect(response).to have_http_status(400) + post api(route, user), branch: 'new_design3', ref: 'foo' + + expect(response).to have_gitlab_http_status(400) expect(json_response['message']).to eq('Invalid reference name') end end - describe "DELETE /projects/:id/repository/branches/:branch" do + 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 + it 'removes branch' do delete api("/projects/#{project.id}/repository/branches/#{branch_name}", user) - expect(response).to have_http_status(204) + expect(response).to have_gitlab_http_status(204) end - it "removes a branch with dots in the branch name" do + it 'removes a branch with dots in the branch name' do delete api("/projects/#{project.id}/repository/branches/#{branch_with_dot.name}", user) - expect(response).to have_http_status(204) + expect(response).to have_gitlab_http_status(204) end it 'returns 404 if branch not exists' do delete api("/projects/#{project.id}/repository/branches/foobar", user) - expect(response).to have_http_status(404) + + expect(response).to have_gitlab_http_status(404) end end - describe "DELETE /projects/:id/repository/merged_branches" do + describe 'DELETE /projects/:id/repository/merged_branches' do before do allow_any_instance_of(Repository).to receive(:rm_branch).and_return(true) end @@ -416,13 +509,14 @@ describe API::Branches do it 'returns 202 with json body' do delete api("/projects/#{project.id}/repository/merged_branches", user) - expect(response).to have_http_status(202) + expect(response).to have_gitlab_http_status(202) expect(json_response['message']).to eql('202 Accepted') end it 'returns a 403 error if guest' do delete api("/projects/#{project.id}/repository/merged_branches", guest) - expect(response).to have_http_status(403) + + expect(response).to have_gitlab_http_status(403) end end end diff --git a/spec/requests/api/deploy_keys_spec.rb b/spec/requests/api/deploy_keys_spec.rb index 32439981b60..d032d72de9c 100644 --- a/spec/requests/api/deploy_keys_spec.rb +++ b/spec/requests/api/deploy_keys_spec.rb @@ -3,8 +3,8 @@ require 'spec_helper' describe API::DeployKeys do let(:user) { create(:user) } let(:admin) { create(:admin) } - let(:project) { create(:empty_project, creator_id: user.id) } - let(:project2) { create(:empty_project, creator_id: user.id) } + 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 @@ -193,7 +193,7 @@ describe API::DeployKeys do end describe 'POST /projects/:id/deploy_keys/:key_id/enable' do - let(:project2) { create(:empty_project) } + let(:project2) { create(:project) } context 'when the user can admin the project' do it 'enables the key' do diff --git a/spec/requests/api/environments_spec.rb b/spec/requests/api/environments_spec.rb index aae03c84e1f..4c5ded7a492 100644 --- a/spec/requests/api/environments_spec.rb +++ b/spec/requests/api/environments_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe API::Environments do let(:user) { create(:user) } let(:non_member) { create(:user) } - let(:project) { create(:empty_project, :private, namespace: user.namespace) } + let(:project) { create(:project, :private, namespace: user.namespace) } let!(:environment) { create(:environment, project: project) } before do diff --git a/spec/requests/api/events_spec.rb b/spec/requests/api/events_spec.rb index a19870a95e8..7a847442469 100644 --- a/spec/requests/api/events_spec.rb +++ b/spec/requests/api/events_spec.rb @@ -1,11 +1,11 @@ require 'spec_helper' -describe API::Events, api: true do +describe API::Events do include ApiHelpers let(:user) { create(:user) } let(:non_member) { create(:user) } let(:other_user) { create(:user, username: 'otheruser') } - let(:private_project) { create(:empty_project, :private, creator_id: user.id, namespace: user.namespace) } + let(:private_project) { create(:project, :private, creator_id: user.id, namespace: user.namespace) } let(:closed_issue) { create(:closed_issue, project: private_project, author: user) } let!(:closed_issue_event) { create(:event, project: private_project, author: user, target: closed_issue, action: Event::CLOSED, created_at: Date.new(2016, 12, 30)) } @@ -60,7 +60,7 @@ describe API::Events, api: true do end context 'when there are multiple events from different projects' do - let(:second_note) { create(:note_on_issue, project: create(:empty_project)) } + let(:second_note) { create(:note_on_issue, project: create(:project)) } before do second_note.project.add_user(user, :developer) @@ -106,7 +106,7 @@ describe API::Events, api: true do end it 'returns 200 status for a public project' do - public_project = create(:empty_project, :public) + public_project = create(:project, :public) get api("/projects/#{public_project.id}/events") diff --git a/spec/requests/api/files_spec.rb b/spec/requests/api/files_spec.rb index 9e268adf950..55c998b13b8 100644 --- a/spec/requests/api/files_spec.rb +++ b/spec/requests/api/files_spec.rb @@ -80,7 +80,7 @@ describe API::Files do context 'when unauthenticated', 'and project is public' do it_behaves_like 'repository files' do - let(:project) { create(:project, :public) } + let(:project) { create(:project, :public, :repository) } let(:current_user) { nil } end end @@ -153,7 +153,7 @@ describe API::Files do context 'when unauthenticated', 'and project is public' do it_behaves_like 'repository raw files' do - let(:project) { create(:project, :public) } + let(:project) { create(:project, :public, :repository) } let(:current_user) { nil } end end diff --git a/spec/requests/api/group_milestones_spec.rb b/spec/requests/api/group_milestones_spec.rb new file mode 100644 index 00000000000..108721c6655 --- /dev/null +++ b/spec/requests/api/group_milestones_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' + +describe API::GroupMilestones do + let(:user) { create(:user) } + let(:group) { create(:group, :private) } + let(:project) { create(:project, namespace: group) } + let!(:group_member) { create(:group_member, group: group, user: user) } + let!(:closed_milestone) { create(:closed_milestone, group: group, title: 'version1', description: 'closed milestone') } + let!(:milestone) { create(:milestone, group: group, title: 'version2', description: 'open milestone') } + + it_behaves_like 'group and project milestones', "/groups/:id/milestones" do + let(:route) { "/groups/#{group.id}/milestones" } + end + + def setup_for_group + context_group.update(visibility_level: Gitlab::VisibilityLevel::PUBLIC) + context_group.add_developer(user) + public_project.update(namespace: context_group) + context_group.reload + end +end diff --git a/spec/requests/api/group_variables_spec.rb b/spec/requests/api/group_variables_spec.rb new file mode 100644 index 00000000000..402ea057cc5 --- /dev/null +++ b/spec/requests/api/group_variables_spec.rb @@ -0,0 +1,221 @@ +require 'spec_helper' + +describe API::GroupVariables do + let(:group) { create(:group) } + let(:user) { create(:user) } + + describe 'GET /groups/:id/variables' do + let!(:variable) { create(:ci_group_variable, group: group) } + + context 'authorized user with proper permissions' do + before do + group.add_master(user) + end + + it 'returns group variables' do + get api("/groups/#{group.id}/variables", user) + + expect(response).to have_http_status(200) + expect(json_response).to be_a(Array) + end + end + + context 'authorized user with invalid permissions' do + it 'does not return group variables' do + get api("/groups/#{group.id}/variables", user) + + expect(response).to have_http_status(403) + end + end + + context 'unauthorized user' do + it 'does not return group variables' do + get api("/groups/#{group.id}/variables") + + expect(response).to have_http_status(401) + end + end + end + + describe 'GET /groups/:id/variables/:key' do + let!(:variable) { create(:ci_group_variable, group: group) } + + context 'authorized user with proper permissions' do + before do + group.add_master(user) + end + + it 'returns group variable details' do + get api("/groups/#{group.id}/variables/#{variable.key}", user) + + expect(response).to have_http_status(200) + expect(json_response['value']).to eq(variable.value) + expect(json_response['protected']).to eq(variable.protected?) + end + + it 'responds with 404 Not Found if requesting non-existing variable' do + get api("/groups/#{group.id}/variables/non_existing_variable", user) + + expect(response).to have_http_status(404) + end + end + + context 'authorized user with invalid permissions' do + it 'does not return group variable details' do + get api("/groups/#{group.id}/variables/#{variable.key}", user) + + expect(response).to have_http_status(403) + end + end + + context 'unauthorized user' do + it 'does not return group variable details' do + get api("/groups/#{group.id}/variables/#{variable.key}") + + expect(response).to have_http_status(401) + end + end + end + + describe 'POST /groups/:id/variables' do + context 'authorized user with proper permissions' do + let!(:variable) { create(:ci_group_variable, group: group) } + + before do + group.add_master(user) + end + + it 'creates variable' do + expect do + post api("/groups/#{group.id}/variables", user), key: 'TEST_VARIABLE_2', value: 'VALUE_2', protected: true + end.to change{group.variables.count}.by(1) + + expect(response).to have_http_status(201) + expect(json_response['key']).to eq('TEST_VARIABLE_2') + expect(json_response['value']).to eq('VALUE_2') + expect(json_response['protected']).to be_truthy + end + + it 'creates variable with optional attributes' do + expect do + post api("/groups/#{group.id}/variables", user), key: 'TEST_VARIABLE_2', value: 'VALUE_2' + end.to change{group.variables.count}.by(1) + + expect(response).to have_http_status(201) + expect(json_response['key']).to eq('TEST_VARIABLE_2') + expect(json_response['value']).to eq('VALUE_2') + expect(json_response['protected']).to be_falsey + end + + it 'does not allow to duplicate variable key' do + expect do + post api("/groups/#{group.id}/variables", user), key: variable.key, value: 'VALUE_2' + end.to change{group.variables.count}.by(0) + + expect(response).to have_http_status(400) + end + end + + context 'authorized user with invalid permissions' do + it 'does not create variable' do + post api("/groups/#{group.id}/variables", user) + + expect(response).to have_http_status(403) + end + end + + context 'unauthorized user' do + it 'does not create variable' do + post api("/groups/#{group.id}/variables") + + expect(response).to have_http_status(401) + end + end + end + + describe 'PUT /groups/:id/variables/:key' do + let!(:variable) { create(:ci_group_variable, group: group) } + + context 'authorized user with proper permissions' do + before do + group.add_master(user) + end + + it 'updates variable data' do + initial_variable = group.variables.first + value_before = initial_variable.value + + put api("/groups/#{group.id}/variables/#{variable.key}", user), value: 'VALUE_1_UP', protected: true + + updated_variable = group.variables.first + + expect(response).to have_http_status(200) + expect(value_before).to eq(variable.value) + expect(updated_variable.value).to eq('VALUE_1_UP') + expect(updated_variable).to be_protected + end + + it 'responds with 404 Not Found if requesting non-existing variable' do + put api("/groups/#{group.id}/variables/non_existing_variable", user) + + expect(response).to have_http_status(404) + end + end + + context 'authorized user with invalid permissions' do + it 'does not update variable' do + put api("/groups/#{group.id}/variables/#{variable.key}", user) + + expect(response).to have_http_status(403) + end + end + + context 'unauthorized user' do + it 'does not update variable' do + put api("/groups/#{group.id}/variables/#{variable.key}") + + expect(response).to have_http_status(401) + end + end + end + + describe 'DELETE /groups/:id/variables/:key' do + let!(:variable) { create(:ci_group_variable, group: group) } + + context 'authorized user with proper permissions' do + before do + group.add_master(user) + end + + it 'deletes variable' do + expect do + delete api("/groups/#{group.id}/variables/#{variable.key}", user) + + expect(response).to have_http_status(204) + end.to change{group.variables.count}.by(-1) + end + + it 'responds with 404 Not Found if requesting non-existing variable' do + delete api("/groups/#{group.id}/variables/non_existing_variable", user) + + expect(response).to have_http_status(404) + end + end + + context 'authorized user with invalid permissions' do + it 'does not delete variable' do + delete api("/groups/#{group.id}/variables/#{variable.key}", user) + + expect(response).to have_http_status(403) + end + end + + context 'unauthorized user' do + it 'does not delete variable' do + delete api("/groups/#{group.id}/variables/#{variable.key}") + + expect(response).to have_http_status(401) + end + end + end +end diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb index 656f098aea8..eba1db15da6 100644 --- a/spec/requests/api/groups_spec.rb +++ b/spec/requests/api/groups_spec.rb @@ -9,9 +9,9 @@ describe API::Groups do let(:admin) { create(:admin) } let!(:group1) { create(:group, avatar: File.open(uploaded_image_temp_path)) } let!(:group2) { create(:group, :private) } - let!(:project1) { create(:empty_project, namespace: group1) } - let!(:project2) { create(:empty_project, namespace: group2) } - let!(:project3) { create(:empty_project, namespace: group1, path: 'test', visibility_level: Gitlab::VisibilityLevel::PRIVATE) } + 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) @@ -167,7 +167,7 @@ describe API::Groups do describe "GET /groups/:id" do context "when authenticated as user" do it "returns one of user1's groups" do - project = create(:empty_project, namespace: group2, path: 'Foo') + project = create(:project, namespace: group2, path: 'Foo') create(:project_group_link, project: project, group: group1) get api("/groups/#{group1.id}", user1) @@ -311,7 +311,7 @@ describe API::Groups do end it 'filters the groups projects' do - public_project = create(:empty_project, :public, path: 'test1', group: group1) + public_project = create(:project, :public, path: 'test1', group: group1) get api("/groups/#{group1.id}/projects", user1), visibility: 'public' @@ -509,8 +509,8 @@ describe API::Groups do end describe "POST /groups/:id/projects/:project_id" do - let(:project) { create(:empty_project) } - let(:project_path) { project.full_path.gsub('/', '%2F') } + let(:project) { create(:project) } + let(:project_path) { CGI.escape(project.full_path) } before(:each) do allow_any_instance_of(Projects::TransferService) diff --git a/spec/requests/api/helpers_spec.rb b/spec/requests/api/helpers_spec.rb index 25ec44fa036..7a1bd76af7a 100644 --- a/spec/requests/api/helpers_spec.rb +++ b/spec/requests/api/helpers_spec.rb @@ -10,8 +10,16 @@ describe API::Helpers do let(:key) { create(:key, user: user) } let(:params) { {} } - let(:env) { { 'REQUEST_METHOD' => 'GET' } } - let(:request) { Rack::Request.new(env) } + let(:csrf_token) { SecureRandom.base64(ActionController::RequestForgeryProtection::AUTHENTICITY_TOKEN_LENGTH) } + let(:env) do + { + 'rack.input' => '', + 'rack.session' => { + _csrf_token: csrf_token + }, + 'REQUEST_METHOD' => 'GET' + } + end let(:header) { } before do @@ -58,7 +66,7 @@ describe API::Helpers do describe ".current_user" do subject { current_user } - describe "Warden authentication" do + describe "Warden authentication", :allow_forgery_protection do before do doorkeeper_guard_returns false end @@ -99,7 +107,17 @@ describe API::Helpers do env['REQUEST_METHOD'] = 'PUT' end - it { is_expected.to be_nil } + context 'without CSRF token' do + it { is_expected.to be_nil } + end + + context 'with CSRF token' do + before do + env['HTTP_X_CSRF_TOKEN'] = csrf_token + end + + it { is_expected.to eq(user) } + end end context "POST request" do @@ -107,7 +125,17 @@ describe API::Helpers do env['REQUEST_METHOD'] = 'POST' end - it { is_expected.to be_nil } + context 'without CSRF token' do + it { is_expected.to be_nil } + end + + context 'with CSRF token' do + before do + env['HTTP_X_CSRF_TOKEN'] = csrf_token + end + + it { is_expected.to eq(user) } + end end context "DELETE request" do @@ -115,7 +143,17 @@ describe API::Helpers do env['REQUEST_METHOD'] = 'DELETE' end - it { is_expected.to be_nil } + context 'without CSRF token' do + it { is_expected.to be_nil } + end + + context 'with CSRF token' do + before do + env['HTTP_X_CSRF_TOKEN'] = csrf_token + end + + it { is_expected.to eq(user) } + end end end end diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb index cab3089c6b1..8a2de23716f 100644 --- a/spec/requests/api/internal_spec.rb +++ b/spec/requests/api/internal_spec.rb @@ -6,7 +6,7 @@ describe API::Internal do let(:project) { create(:project, :repository) } let(:secret_token) { Gitlab::Shell.secret_token } - describe "GET /internal/check", no_db: true do + describe "GET /internal/check" do it do get api("/internal/check"), secret_token: secret_token @@ -301,7 +301,7 @@ describe API::Internal do context 'project as /namespace/project' do it do - pull(key, project_with_repo_path('/' + project.path_with_namespace)) + pull(key, project_with_repo_path('/' + project.full_path)) expect(response).to have_http_status(200) expect(json_response["status"]).to be_truthy @@ -312,7 +312,7 @@ describe API::Internal do context 'project as namespace/project' do it do - pull(key, project_with_repo_path(project.path_with_namespace)) + pull(key, project_with_repo_path(project.full_path)) expect(response).to have_http_status(200) expect(json_response["status"]).to be_truthy @@ -350,7 +350,7 @@ describe API::Internal do end context "blocked user" do - let(:personal_project) { create(:empty_project, namespace: user.namespace) } + let(:personal_project) { create(:project, namespace: user.namespace) } before do user.block diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index 9837fedb522..7d120e4a234 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -1,11 +1,9 @@ require 'spec_helper' -describe API::Issues do - include EmailHelpers - +describe API::Issues, :mailer do set(:user) { create(:user) } set(:project) do - create(:empty_project, :public, creator_id: user.id, namespace: user.namespace) + create(:project, :public, creator_id: user.id, namespace: user.namespace) end let(:user2) { create(:user) } @@ -71,7 +69,6 @@ describe API::Issues do expect(response).to have_http_status(401) end end - context "when authenticated" do let(:first_issue) { json_response.first } @@ -105,6 +102,42 @@ describe API::Issues do expect(json_response.second['id']).to eq(closed_issue.id) end + it 'returns issues assigned to me' do + issue2 = create(:issue, assignees: [user2], project: project) + + get api('/issues', user2), scope: 'assigned-to-me' + + expect_paginated_array_response(size: 1) + expect(first_issue['id']).to eq(issue2.id) + end + + it 'returns issues authored by the given author id' do + issue2 = create(:issue, author: user2, project: project) + + get api('/issues', user), author_id: user2.id, scope: 'all' + + expect_paginated_array_response(size: 1) + expect(first_issue['id']).to eq(issue2.id) + end + + it 'returns issues assigned to the given assignee id' do + issue2 = create(:issue, assignees: [user2], project: project) + + get api('/issues', user), assignee_id: user2.id, scope: 'all' + + expect_paginated_array_response(size: 1) + expect(first_issue['id']).to eq(issue2.id) + end + + it 'returns issues authored by the given author id and assigned to the given assignee id' do + issue2 = create(:issue, author: user2, assignees: [user2], project: project) + + get api('/issues', user), author_id: user2.id, assignee_id: user2.id, scope: 'all' + + expect_paginated_array_response(size: 1) + expect(first_issue['id']).to eq(issue2.id) + end + it 'returns issues matching given search string for title' do get api("/issues", user), search: issue.title @@ -261,7 +294,7 @@ describe API::Issues do describe "GET /groups/:id/issues" do let!(:group) { create(:group) } - let!(:group_project) { create(:empty_project, :public, creator_id: user.id, namespace: group) } + let!(:group_project) { create(:project, :public, creator_id: user.id, namespace: group) } let!(:group_closed_issue) do create :closed_issue, author: user, @@ -483,7 +516,7 @@ describe API::Issues do end it "returns 404 on private projects for other users" do - private_project = create(:empty_project, :private) + private_project = create(:project, :private) create(:issue, project: private_project) get api("/projects/#{private_project.id}/issues", non_member) @@ -492,7 +525,7 @@ describe API::Issues do end it 'returns no issues when user has access to project but not issues' do - restricted_project = create(:empty_project, :public, :issues_private) + restricted_project = create(:project, :public, :issues_private) create(:issue, project: restricted_project) get api("/projects/#{restricted_project.id}/issues", non_member) @@ -693,6 +726,19 @@ describe API::Issues do expect(json_response['confidential']).to be_falsy end + context 'links exposure' do + it 'exposes related resources full URIs' do + get api("/projects/#{project.id}/issues/#{issue.iid}", user) + + links = json_response['_links'] + + expect(links['self']).to end_with("/api/v4/projects/#{project.id}/issues/#{issue.iid}") + expect(links['notes']).to end_with("/api/v4/projects/#{project.id}/issues/#{issue.iid}/notes") + expect(links['award_emoji']).to end_with("/api/v4/projects/#{project.id}/issues/#{issue.iid}/award_emoji") + expect(links['project']).to end_with("/api/v4/projects/#{project.id}") + end + end + it "returns a project issue by internal id" do get api("/projects/#{project.id}/issues/#{issue.iid}", user) @@ -1211,7 +1257,7 @@ describe API::Issues do put api("/projects/#{project.id}/issues/#{closed_issue.iid}", user), state_event: 'reopen' expect(response).to have_http_status(200) - expect(json_response['state']).to eq 'reopened' + expect(json_response['state']).to eq 'opened' end context 'when an admin or owner makes the request' do @@ -1251,7 +1297,7 @@ describe API::Issues do context "when the user is project owner" do let(:owner) { create(:user) } - let(:project) { create(:empty_project, namespace: owner.namespace) } + let(:project) { create(:project, namespace: owner.namespace) } it "deletes the issue if an admin requests it" do delete api("/projects/#{project.id}/issues/#{issue.iid}", owner) @@ -1276,8 +1322,8 @@ describe API::Issues do end describe '/projects/:id/issues/:issue_iid/move' do - let!(:target_project) { create(:empty_project, path: 'project2', creator_id: user.id, namespace: user.namespace ) } - let!(:target_project2) { create(:empty_project, creator_id: non_member.id, namespace: non_member.namespace ) } + let!(:target_project) { create(:project, path: 'project2', 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 api("/projects/#{project.id}/issues/#{issue.iid}/move", user), diff --git a/spec/requests/api/jobs_spec.rb b/spec/requests/api/jobs_spec.rb index 8d647eb1c7e..f56baf9663d 100644 --- a/spec/requests/api/jobs_spec.rb +++ b/spec/requests/api/jobs_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe API::Jobs, :api do +describe API::Jobs do let!(:project) do create(:project, :repository, public_builds: false) end diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb index f7e2f1908bb..5a4257d1009 100644 --- a/spec/requests/api/labels_spec.rb +++ b/spec/requests/api/labels_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe API::Labels do let(:user) { create(:user) } - let(:project) { create(:empty_project, creator_id: user.id, namespace: user.namespace) } + 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) } diff --git a/spec/requests/api/members_spec.rb b/spec/requests/api/members_spec.rb index e095053fa03..06aca698c91 100644 --- a/spec/requests/api/members_spec.rb +++ b/spec/requests/api/members_spec.rb @@ -7,7 +7,7 @@ describe API::Members do let(:stranger) { create(:user) } let(:project) do - create(:empty_project, :public, :access_requestable, creator_id: master.id, namespace: master.namespace) do |project| + create(:project, :public, :access_requestable, creator_id: master.id, namespace: master.namespace) do |project| project.team << [developer, :developer] project.team << [master, :master] project.request_access(access_requester) diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index 35b6522ea98..9eda6836ded 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -26,6 +26,100 @@ describe API::MergeRequests do project.team << [user, :reporter] end + describe 'GET /merge_requests' do + context 'when unauthenticated' do + it 'returns authentication error' do + get api('/merge_requests') + + expect(response).to have_http_status(401) + end + end + + context 'when authenticated' do + let!(:project2) { create(:project, :public, namespace: user.namespace) } + let!(:merge_request2) { create(:merge_request, :simple, author: user, assignee: user, source_project: project2, target_project: project2) } + let(:user2) { create(:user) } + + it 'returns an array of all merge requests' do + get api('/merge_requests', user), scope: :all + + expect(response).to have_http_status(200) + expect(response).to include_pagination_headers + expect(json_response).to be_an Array + expect(json_response.map { |mr| mr['id'] }) + .to contain_exactly(merge_request.id, merge_request_closed.id, merge_request_merged.id, merge_request2.id) + end + + it 'does not return unauthorized merge requests' do + private_project = create(:project, :private) + merge_request3 = create(:merge_request, :simple, source_project: private_project, target_project: private_project, source_branch: 'other-branch') + + get api('/merge_requests', user), scope: :all + + expect(response).to have_http_status(200) + expect(response).to include_pagination_headers + expect(json_response).to be_an Array + expect(json_response.map { |mr| mr['id'] }) + .not_to include(merge_request3.id) + end + + it 'returns an array of merge requests created by current user if no scope is given' do + merge_request3 = create(:merge_request, :simple, author: user2, assignee: user, source_project: project2, target_project: project2, source_branch: 'other-branch') + + get api('/merge_requests', user2) + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.first['id']).to eq(merge_request3.id) + end + + it 'returns an array of merge requests authored by the given user' do + merge_request3 = create(:merge_request, :simple, author: user2, assignee: user, source_project: project2, target_project: project2, source_branch: 'other-branch') + + get api('/merge_requests', user), author_id: user2.id, scope: :all + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.first['id']).to eq(merge_request3.id) + end + + it 'returns an array of merge requests assigned to the given user' do + merge_request3 = create(:merge_request, :simple, author: user, assignee: user2, source_project: project2, target_project: project2, source_branch: 'other-branch') + + get api('/merge_requests', user), assignee_id: user2.id, scope: :all + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.first['id']).to eq(merge_request3.id) + end + + it 'returns an array of merge requests assigned to me' do + merge_request3 = create(:merge_request, :simple, author: user, assignee: user2, source_project: project2, target_project: project2, source_branch: 'other-branch') + + get api('/merge_requests', user2), scope: 'assigned-to-me' + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.first['id']).to eq(merge_request3.id) + end + + it 'returns an array of merge requests created by me' do + merge_request3 = create(:merge_request, :simple, author: user2, assignee: user, source_project: project2, target_project: project2, source_branch: 'other-branch') + + get api('/merge_requests', user2), scope: 'created-by-me' + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.first['id']).to eq(merge_request3.id) + end + end + end + describe "GET /projects/:id/merge_requests" do context "when unauthenticated" do it "returns authentication error" do @@ -199,6 +293,26 @@ describe API::MergeRequests do 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) + + get api("/projects/#{project.id}/merge_requests?labels=#{bug_label.title}&milestone=#{milestone1.title}&state=merged", user) + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.first['id']).to eq(mr2.id) + end + context "with ordering" do before do @mr_later = mr_with_later_created_and_updated_at_time @@ -463,8 +577,8 @@ describe API::MergeRequests do context 'forked projects' do let!(:user2) { create(:user) } - let!(:fork_project) { create(:empty_project, forked_from_project: project, namespace: user2.namespace, creator_id: user2.id) } - let!(:unrelated_project) { create(:empty_project, namespace: create(:user).namespace, creator_id: user2.id) } + let!(:fork_project) { create(:project, forked_from_project: project, namespace: user2.namespace, creator_id: user2.id) } + let!(:unrelated_project) { create(:project, namespace: create(:user).namespace, creator_id: user2.id) } before :each do |each| fork_project.team << [user2, :reporter] @@ -793,7 +907,7 @@ describe API::MergeRequests do end it 'handles external issues' do - jira_project = create(:jira_project, :public, name: 'JIR_EXT1') + jira_project = create(:jira_project, :public, :repository, name: 'JIR_EXT1') ext_issue = ExternalIssue.new("#{jira_project.name}-123", jira_project) issue = create(:issue, project: jira_project) description = "Closes #{ext_issue.to_reference(jira_project)}\ncloses #{issue.to_reference}" @@ -815,7 +929,7 @@ describe API::MergeRequests do end it 'returns 403 if the user has no access to the merge request' do - project = create(:empty_project, :private) + project = create(:project, :private) merge_request = create(:merge_request, :simple, source_project: project) guest = create(:user) project.team << [guest, :guest] diff --git a/spec/requests/api/milestones_spec.rb b/spec/requests/api/milestones_spec.rb deleted file mode 100644 index ab5ea3e8f2c..00000000000 --- a/spec/requests/api/milestones_spec.rb +++ /dev/null @@ -1,385 +0,0 @@ -require 'spec_helper' - -describe API::Milestones do - let(:user) { create(:user) } - let!(:project) { create(:empty_project, namespace: user.namespace ) } - let!(:closed_milestone) { create(:closed_milestone, project: project, title: 'version1', description: 'closed milestone') } - let!(:milestone) { create(:milestone, project: project, title: 'version2', description: 'open milestone') } - let(:label_1) { create(:label, title: 'label_1', project: project, priority: 1) } - let(:label_2) { create(:label, title: 'label_2', project: project, priority: 2) } - let(:label_3) { create(:label, title: 'label_3', project: project) } - - before do - project.team << [user, :developer] - end - - describe 'GET /projects/:id/milestones' do - it 'returns project milestones' do - get api("/projects/#{project.id}/milestones", user) - - expect(response).to have_http_status(200) - expect(response).to include_pagination_headers - 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 api("/projects/#{project.id}/milestones") - - expect(response).to have_http_status(401) - end - - it 'returns an array of active milestones' do - get api("/projects/#{project.id}/milestones?state=active", user) - - expect(response).to have_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['id']).to eq(milestone.id) - end - - it 'returns an array of closed milestones' do - get api("/projects/#{project.id}/milestones?state=closed", user) - - expect(response).to have_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['id']).to eq(closed_milestone.id) - end - - it 'returns an array of milestones specified by iids' do - other_milestone = create(:milestone, project: project) - - get api("/projects/#{project.id}/milestones", user), iids: [closed_milestone.iid, other_milestone.iid] - - expect(response).to have_http_status(200) - expect(json_response).to be_an Array - expect(json_response.length).to eq(2) - expect(json_response.map{ |m| m['id'] }).to match_array([closed_milestone.id, other_milestone.id]) - end - - it 'does not return any milestone if none found' do - get api("/projects/#{project.id}/milestones", user), iids: [Milestone.maximum(:iid).succ] - - expect(response).to have_http_status(200) - expect(json_response).to be_an Array - expect(json_response.length).to eq(0) - end - end - - describe 'GET /projects/:id/milestones/:milestone_id' do - it 'returns a project milestone by id' do - get api("/projects/#{project.id}/milestones/#{milestone.id}", user) - - expect(response).to have_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 iids array' do - get api("/projects/#{project.id}/milestones?iids=#{closed_milestone.iid}", user) - - expect(response.status).to eq 200 - expect(response).to include_pagination_headers - expect(json_response.size).to eq(1) - 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 searching for title' do - get api("/projects/#{project.id}/milestones", user), search: 'version2' - - expect(response).to have_http_status(200) - expect(response).to include_pagination_headers - expect(json_response.size).to eq(1) - expect(json_response.first['title']).to eq milestone.title - expect(json_response.first['id']).to eq milestone.id - end - - it 'returns a project milestones by searching for description' do - get api("/projects/#{project.id}/milestones", user), search: 'open' - - expect(response).to have_http_status(200) - expect(response).to include_pagination_headers - expect(json_response.size).to eq(1) - expect(json_response.first['title']).to eq milestone.title - expect(json_response.first['id']).to eq milestone.id - end - end - - describe 'GET /projects/:id/milestones/:milestone_id' do - it 'returns a project milestone by id' do - get api("/projects/#{project.id}/milestones/#{milestone.id}", user) - - expect(response).to have_http_status(200) - expect(json_response['title']).to eq(milestone.title) - expect(json_response['iid']).to eq(milestone.iid) - end - - it 'returns 401 error if user not authenticated' do - get api("/projects/#{project.id}/milestones/#{milestone.id}") - - expect(response).to have_http_status(401) - end - - it 'returns a 404 error if milestone id not found' do - get api("/projects/#{project.id}/milestones/1234", user) - - expect(response).to have_http_status(404) - end - end - - describe 'POST /projects/:id/milestones' do - it 'creates a new project milestone' do - post api("/projects/#{project.id}/milestones", user), title: 'new milestone' - - expect(response).to have_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 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_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 api("/projects/#{project.id}/milestones", user) - - expect(response).to have_http_status(400) - end - - it 'returns a 400 error if params are invalid (duplicate title)' do - post api("/projects/#{project.id}/milestones", user), - title: milestone.title, description: 'release', due_date: '2013-03-02' - - expect(response).to have_http_status(400) - end - - it 'creates a new project with reserved html characters' do - post api("/projects/#{project.id}/milestones", user), title: 'foo & bar 1.1 -> 2.2' - - expect(response).to have_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 api("/projects/#{project.id}/milestones/#{milestone.id}", user), - title: 'updated title' - - expect(response).to have_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 api("/projects/#{project.id}/milestones/#{milestone.id}", user), due_date: nil - - expect(response).to have_http_status(200) - expect(json_response['due_date']).to be_nil - end - - it 'returns a 404 error if milestone id not found' do - put api("/projects/#{project.id}/milestones/1234", user), - title: 'updated title' - - expect(response).to have_http_status(404) - end - end - - describe 'PUT /projects/:id/milestones/:milestone_id to close milestone' do - it 'updates a project milestone' do - put api("/projects/#{project.id}/milestones/#{milestone.id}", user), - state_event: 'close' - expect(response).to have_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 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 api("/projects/#{project.id}/milestones/#{milestone.id}/issues", user) - - expect(response).to have_http_status(200) - expect(response).to include_pagination_headers - expect(json_response).to be_an Array - expect(json_response.first['milestone']['title']).to eq(milestone.title) - end - - it 'returns project issues sorted by label priority' do - issue_1 = create(:labeled_issue, project: project, milestone: milestone, labels: [label_3]) - issue_2 = create(:labeled_issue, project: project, milestone: milestone, labels: [label_1]) - issue_3 = create(:labeled_issue, project: project, milestone: milestone, labels: [label_2]) - - get api("/projects/#{project.id}/milestones/#{milestone.id}/issues", user) - - expect(json_response.first['id']).to eq(issue_2.id) - expect(json_response.second['id']).to eq(issue_3.id) - expect(json_response.third['id']).to eq(issue_1.id) - end - - it 'matches V4 response schema for a list of issues' do - get api("/projects/#{project.id}/milestones/#{milestone.id}/issues", user) - - expect(response).to have_http_status(200) - expect(response).to match_response_schema('public_api/v4/issues') - end - - it 'returns a 401 error if user not authenticated' do - get api("/projects/#{project.id}/milestones/#{milestone.id}/issues") - - expect(response).to have_http_status(401) - end - - describe 'confidential issues' do - let(:public_project) { create(:empty_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.team << [user, :developer] - milestone.issues << issue << confidential_issue - end - - it 'returns confidential issues to team members' do - get api("/projects/#{public_project.id}/milestones/#{milestone.id}/issues", user) - - expect(response).to have_http_status(200) - expect(response).to include_pagination_headers - 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.team << [member, :guest] - - get api("/projects/#{public_project.id}/milestones/#{milestone.id}/issues", member) - - expect(response).to have_http_status(200) - expect(response).to include_pagination_headers - 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 api("/projects/#{public_project.id}/milestones/#{milestone.id}/issues", create(:user)) - - expect(response).to have_http_status(200) - expect(response).to include_pagination_headers - 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 'returns issues ordered by label priority' do - issue.labels << label_2 - confidential_issue.labels << label_1 - - get api("/projects/#{public_project.id}/milestones/#{milestone.id}/issues", user) - - expect(response).to have_http_status(200) - expect(response).to include_pagination_headers - expect(json_response).to be_an Array - expect(json_response.size).to eq(2) - expect(json_response.first['id']).to eq(confidential_issue.id) - expect(json_response.second['id']).to eq(issue.id) - end - end - end - - describe 'GET /projects/:id/milestones/:milestone_id/merge_requests' do - let(:merge_request) { create(:merge_request, source_project: project) } - let(:another_merge_request) { create(:merge_request, :simple, source_project: project) } - - before do - milestone.merge_requests << merge_request - end - - it 'returns project merge_requests for a particular milestone' do - # eager-load another_merge_request - another_merge_request - get api("/projects/#{project.id}/milestones/#{milestone.id}/merge_requests", user) - - expect(response).to have_http_status(200) - expect(json_response).to be_an Array - expect(json_response.size).to eq(1) - expect(json_response.first['title']).to eq(merge_request.title) - expect(json_response.first['milestone']['title']).to eq(milestone.title) - end - - it 'returns project merge_requests sorted by label priority' do - merge_request_1 = create(:labeled_merge_request, source_branch: 'branch_1', source_project: project, milestone: milestone, labels: [label_2]) - merge_request_2 = create(:labeled_merge_request, source_branch: 'branch_2', source_project: project, milestone: milestone, labels: [label_1]) - merge_request_3 = create(:labeled_merge_request, source_branch: 'branch_3', source_project: project, milestone: milestone, labels: [label_3]) - - get api("/projects/#{project.id}/milestones/#{milestone.id}/merge_requests", user) - - expect(json_response.first['id']).to eq(merge_request_2.id) - expect(json_response.second['id']).to eq(merge_request_1.id) - expect(json_response.third['id']).to eq(merge_request_3.id) - end - - it 'returns a 404 error if milestone id not found' do - get api("/projects/#{project.id}/milestones/1234/merge_requests", user) - - expect(response).to have_http_status(404) - end - - it 'returns a 404 if the user has no access to the milestone' do - new_user = create :user - get api("/projects/#{project.id}/milestones/#{milestone.id}/merge_requests", new_user) - - expect(response).to have_http_status(404) - end - - it 'returns a 401 error if user not authenticated' do - get api("/projects/#{project.id}/milestones/#{milestone.id}/merge_requests") - - expect(response).to have_http_status(401) - end - - it 'returns merge_requests ordered by position asc' do - milestone.merge_requests << another_merge_request - another_merge_request.labels << label_1 - merge_request.labels << label_2 - - get api("/projects/#{project.id}/milestones/#{milestone.id}/merge_requests", user) - - expect(response).to have_http_status(200) - expect(response).to include_pagination_headers - expect(json_response).to be_an Array - expect(json_response.size).to eq(2) - expect(json_response.first['id']).to eq(another_merge_request.id) - expect(json_response.second['id']).to eq(merge_request.id) - end - end -end diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb index 4701ad585c9..75e5062a99c 100644 --- a/spec/requests/api/notes_spec.rb +++ b/spec/requests/api/notes_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe API::Notes do let(:user) { create(:user) } - let!(:project) { create(:empty_project, :public, namespace: user.namespace) } + 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) } @@ -13,12 +13,12 @@ describe API::Notes do # For testing the cross-reference of a private issue in a public issue let(:private_user) { create(:user) } let(:private_project) do - create(:empty_project, namespace: private_user.namespace) + create(:project, namespace: private_user.namespace) .tap { |p| p.team << [private_user, :master] } end let(:private_issue) { create(:issue, project: private_project) } - let(:ext_proj) { create(:empty_project, :public) } + let(:ext_proj) { create(:project, :public) } let(:ext_issue) { create(:issue, project: ext_proj) } let!(:cross_reference_note) do @@ -272,7 +272,7 @@ describe API::Notes do context 'when user does not have access to read the noteable' do it 'responds with 404' do - project = create(:empty_project, :private) { |p| p.add_guest(user) } + project = create(:project, :private) { |p| p.add_guest(user) } issue = create(:issue, :confidential, project: project) post api("/projects/#{project.id}/issues/#{issue.iid}/notes", user), @@ -283,7 +283,7 @@ describe API::Notes do end context 'when user does not have access to create noteable' do - let(:private_issue) { create(:issue, project: create(:empty_project, :private)) } + let(:private_issue) { create(:issue, project: create(:project, :private)) } ## # We are posting to project user has access to, but we use issue id diff --git a/spec/requests/api/notification_settings_spec.rb b/spec/requests/api/notification_settings_spec.rb index f619b7e6eaf..7968659a1ec 100644 --- a/spec/requests/api/notification_settings_spec.rb +++ b/spec/requests/api/notification_settings_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe API::NotificationSettings do let(:user) { create(:user) } let!(:group) { create(:group) } - let!(:project) { create(:empty_project, :public, creator_id: user.id, namespace: group) } + let!(:project) { create(:project, :public, creator_id: user.id, namespace: group) } describe "GET /notification_settings" do it "returns global notification settings for the current user" do @@ -72,8 +72,8 @@ describe API::NotificationSettings do expect(response).to have_http_status(200) expect(json_response['level']).to eq(user.reload.notification_settings_for(project).level) - expect(json_response['events']['new_note']).to eq(true) - expect(json_response['events']['new_issue']).to eq(false) + expect(json_response['events']['new_note']).to be_truthy + expect(json_response['events']['new_issue']).to be_falsey end end diff --git a/spec/requests/api/pipeline_schedules_spec.rb b/spec/requests/api/pipeline_schedules_spec.rb index b34555d2815..9ff2b782b52 100644 --- a/spec/requests/api/pipeline_schedules_spec.rb +++ b/spec/requests/api/pipeline_schedules_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe API::PipelineSchedules do set(:developer) { create(:user) } set(:user) { create(:user) } - set(:project) { create(:project) } + set(:project) { create(:project, :repository) } before do project.add_developer(developer) diff --git a/spec/requests/api/project_hooks_spec.rb b/spec/requests/api/project_hooks_spec.rb index 0f9330b062d..2829c243af3 100644 --- a/spec/requests/api/project_hooks_spec.rb +++ b/spec/requests/api/project_hooks_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe API::ProjectHooks, 'ProjectHooks' do let(:user) { create(:user) } let(:user3) { create(:user) } - let!(:project) { create(:empty_project, creator_id: user.id, namespace: user.namespace) } + let!(:project) { create(:project, creator_id: user.id, namespace: user.namespace) } let!(:hook) do create(:project_hook, :all_events_enabled, @@ -205,7 +205,7 @@ describe API::ProjectHooks, 'ProjectHooks' do 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(:empty_project) + other_project = create(:project) other_project.team << [test_user, :master] delete api("/projects/#{other_project.id}/hooks/#{hook.id}", test_user) diff --git a/spec/requests/api/project_milestones_spec.rb b/spec/requests/api/project_milestones_spec.rb new file mode 100644 index 00000000000..72e1574b55f --- /dev/null +++ b/spec/requests/api/project_milestones_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +describe API::ProjectMilestones do + let(:user) { create(:user) } + let!(:project) { create(:project, namespace: user.namespace ) } + let!(:closed_milestone) { create(:closed_milestone, project: project, title: 'version1', description: 'closed milestone') } + let!(:milestone) { create(:milestone, project: project, title: 'version2', description: 'open milestone') } + + before do + project.team << [user, :developer] + end + + it_behaves_like 'group and project milestones', "/projects/:id/milestones" do + let(:route) { "/projects/#{project.id}/milestones" } + 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 api("/projects/#{project.id}/milestones/#{milestone.id}", user), + state_event: 'close' + end + end +end diff --git a/spec/requests/api/project_snippets_spec.rb b/spec/requests/api/project_snippets_spec.rb index f220972bae3..2b541f5719e 100644 --- a/spec/requests/api/project_snippets_spec.rb +++ b/spec/requests/api/project_snippets_spec.rb @@ -1,7 +1,7 @@ require 'rails_helper' describe API::ProjectSnippets do - let(:project) { create(:empty_project, :public) } + let(:project) { create(:project, :public) } let(:user) { create(:user) } let(:admin) { create(:admin) } diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 457f64cc88c..b9ebf6c4c16 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -8,8 +8,8 @@ describe API::Projects do let(:user2) { create(:user) } let(:user3) { create(:user) } let(:admin) { create(:admin) } - let(:project) { create(:empty_project, creator_id: user.id, namespace: user.namespace) } - let(:project2) { create(:empty_project, path: 'project2', creator_id: user.id, namespace: user.namespace) } + let(:project) { create(:project, creator_id: user.id, namespace: user.namespace) } + let(:project2) { create(:project, path: 'project2', 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) } @@ -33,7 +33,7 @@ describe API::Projects do access_level: ProjectMember::MASTER) end let(:project4) do - create(:empty_project, + create(:project, name: 'third_project', path: 'third_project', creator_id: user4.id, @@ -61,7 +61,7 @@ describe API::Projects do if defined?(additional_project) additional_project else - create(:empty_project, :public) + create(:project, :public) end expect do @@ -70,7 +70,7 @@ describe API::Projects do end end - let!(:public_project) { create(:empty_project, :public, name: 'public_project') } + let!(:public_project) { create(:project, :public, name: 'public_project') } before do project project2 @@ -103,12 +103,12 @@ describe API::Projects do context 'when some projects are in a group' do before do - create(:empty_project, :public, group: create(:group)) + create(:project, :public, group: create(:group)) end it_behaves_like 'projects response without N + 1 queries' do let(:current_user) { user } - let(:additional_project) { create(:empty_project, :public, group: create(:group)) } + let(:additional_project) { create(:project, :public, group: create(:group)) } end end @@ -268,7 +268,7 @@ describe API::Projects do end context 'and with starred=true' do - let(:public_project) { create(:empty_project, :public) } + let(:public_project) { create(:project, :public) } before do project_member @@ -286,11 +286,11 @@ describe API::Projects do end context 'and with all query parameters' do - let!(:project5) { create(:empty_project, :public, path: 'gitlab5', namespace: create(:namespace)) } - let!(:project6) { create(:empty_project, :public, path: 'project6', namespace: user.namespace) } - let!(:project7) { create(:empty_project, :public, path: 'gitlab7', namespace: user.namespace) } - let!(:project8) { create(:empty_project, path: 'gitlab8', namespace: user.namespace) } - let!(:project9) { create(:empty_project, :public, path: 'gitlab9') } + let!(:project5) { create(:project, :public, path: 'gitlab5', namespace: create(:namespace)) } + let!(:project6) { create(:project, :public, path: 'project6', namespace: user.namespace) } + let!(:project7) { create(:project, :public, path: 'gitlab7', namespace: user.namespace) } + let!(:project8) { create(:project, path: 'gitlab8', namespace: user.namespace) } + let!(:project9) { create(:project, :public, path: 'gitlab9') } before do user.update_attributes(starred_projects: [project5, project7, project8, project9]) @@ -539,7 +539,7 @@ describe API::Projects do end describe 'GET /users/:user_id/projects/' do - let!(:public_project) { create(:empty_project, :public, name: 'public_project', creator_id: user4.id, namespace: user4.namespace) } + let!(:public_project) { create(:project, :public, name: 'public_project', creator_id: user4.id, namespace: user4.namespace) } it 'returns error when user not found' do get api('/users/9999/projects/') @@ -682,7 +682,7 @@ describe API::Projects do describe 'GET /projects/:id' do context 'when unauthenticated' do it 'returns the public projects' do - public_project = create(:empty_project, :public) + public_project = create(:project, :public) get api("/projects/#{public_project.id}") @@ -766,9 +766,9 @@ describe API::Projects do it 'handles users with dots' do dot_user = create(:user, username: 'dot.user') - project = create(:empty_project, creator_id: dot_user.id, namespace: dot_user.namespace) + project = create(:project, creator_id: dot_user.id, namespace: dot_user.namespace) - get api("/projects/#{dot_user.namespace.name}%2F#{project.path}", dot_user) + get api("/projects/#{CGI.escape(project.full_path)}", dot_user) expect(response).to have_http_status(200) expect(json_response['name']).to eq(project.name) end @@ -815,6 +815,38 @@ describe API::Projects do expect(json_response).not_to include("import_error") end + context 'links exposure' do + it 'exposes related resources full URIs' do + get api("/projects/#{project.id}", user) + + links = json_response['_links'] + + expect(links['self']).to end_with("/api/v4/projects/#{project.id}") + expect(links['issues']).to end_with("/api/v4/projects/#{project.id}/issues") + expect(links['merge_requests']).to end_with("/api/v4/projects/#{project.id}/merge_requests") + expect(links['repo_branches']).to end_with("/api/v4/projects/#{project.id}/repository/branches") + expect(links['labels']).to end_with("/api/v4/projects/#{project.id}/labels") + expect(links['events']).to end_with("/api/v4/projects/#{project.id}/events") + expect(links['members']).to end_with("/api/v4/projects/#{project.id}/members") + end + + it 'filters related URIs when their feature is not enabled' do + project = create(:project, :public, + :merge_requests_disabled, + :issues_disabled, + creator_id: user.id, + namespace: user.namespace) + + get api("/projects/#{project.id}", user) + + links = json_response['_links'] + + expect(links.has_key?('merge_requests')).to be_falsy + expect(links.has_key?('issues')).to be_falsy + expect(links['self']).to end_with("/api/v4/projects/#{project.id}") + end + end + describe 'permissions' do context 'all projects' do before do @@ -844,7 +876,7 @@ describe API::Projects do end context 'group project' do - let(:project2) { create(:empty_project, group: create(:group)) } + let(:project2) { create(:project, group: create(:group)) } before do project2.group.add_owner(user) @@ -884,7 +916,7 @@ describe API::Projects do context 'when unauthenticated' do it_behaves_like 'project users response' do - let(:project) { create(:empty_project, :public) } + let(:project) { create(:project, :public) } let(:current_user) { nil } end end @@ -1004,11 +1036,11 @@ describe API::Projects do end describe 'fork management' do - let(:project_fork_target) { create(:empty_project) } - let(:project_fork_source) { create(:empty_project, :public) } + 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(:empty_project, :public) } + let(:new_project_fork_source) { create(:project, :public) } it "is not available for non admin users" do post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", user) @@ -1049,7 +1081,7 @@ describe API::Projects do end context 'when users belong to project group' do - let(:project_fork_target) { create(:empty_project, group: create(:group)) } + let(:project_fork_target) { create(:project, group: create(:group)) } before do project_fork_target.group.add_owner user diff --git a/spec/requests/api/protected_branches_spec.rb b/spec/requests/api/protected_branches_spec.rb new file mode 100644 index 00000000000..e4f9c47fb33 --- /dev/null +++ b/spec/requests/api/protected_branches_spec.rb @@ -0,0 +1,232 @@ +require 'spec_helper' + +describe API::ProtectedBranches do + let(:user) { create(:user) } + let!(:project) { create(:project, :repository) } + let(:protected_name) { 'feature' } + let(:branch_name) { protected_name } + let!(:protected_branch) do + create(:protected_branch, project: project, name: protected_name) + end + + describe "GET /projects/:id/protected_branches" do + let(:route) { "/projects/#{project.id}/protected_branches" } + + shared_examples_for 'protected branches' do + it 'returns the protected branches' do + get api(route, user), per_page: 100 + + expect(response).to have_gitlab_http_status(200) + expect(response).to include_pagination_headers + expect(json_response).to be_an Array + + protected_branch_names = json_response.map { |x| x['name'] } + expected_branch_names = project.protected_branches.map { |x| x['name'] } + expect(protected_branch_names).to match_array(expected_branch_names) + end + end + + context 'when authenticated as a master' do + before do + project.add_master(user) + end + + it_behaves_like 'protected branches' + end + + context 'when authenticated as a guest' do + before do + project.add_guest(user) + end + + it_behaves_like '403 response' do + let(:request) { get api(route, user) } + end + end + end + + describe "GET /projects/:id/protected_branches/:branch" do + let(:route) { "/projects/#{project.id}/protected_branches/#{branch_name}" } + + shared_examples_for 'protected branch' do + it 'returns the protected branch' do + get api(route, user) + + expect(response).to have_gitlab_http_status(200) + expect(json_response['name']).to eq(branch_name) + expect(json_response['push_access_levels'][0]['access_level']).to eq(::Gitlab::Access::MASTER) + expect(json_response['merge_access_levels'][0]['access_level']).to eq(::Gitlab::Access::MASTER) + end + + context 'when protected branch does not exist' do + let(:branch_name) { 'unknown' } + + it_behaves_like '404 response' do + let(:request) { get api(route, user) } + let(:message) { '404 Not found' } + end + end + end + + context 'when authenticated as a master' do + before do + project.add_master(user) + end + + it_behaves_like 'protected branch' + + context 'when protected branch contains a wildcard' do + let(:protected_name) { 'feature*' } + + it_behaves_like 'protected branch' + end + end + + context 'when authenticated as a guest' do + before do + project.add_guest(user) + end + + it_behaves_like '403 response' do + let(:request) { get api(route, user) } + end + end + end + + describe 'POST /projects/:id/protected_branches' do + let(:branch_name) { 'new_branch' } + + context 'when authenticated as a master' do + before do + project.add_master(user) + end + + it 'protects a single branch' do + post api("/projects/#{project.id}/protected_branches", user), name: branch_name + + expect(response).to have_gitlab_http_status(201) + expect(json_response['name']).to eq(branch_name) + expect(json_response['push_access_levels'][0]['access_level']).to eq(Gitlab::Access::MASTER) + expect(json_response['merge_access_levels'][0]['access_level']).to eq(Gitlab::Access::MASTER) + end + + it 'protects a single branch and developers can push' do + post api("/projects/#{project.id}/protected_branches", user), + name: branch_name, push_access_level: 30 + + expect(response).to have_gitlab_http_status(201) + expect(json_response['name']).to eq(branch_name) + expect(json_response['push_access_levels'][0]['access_level']).to eq(Gitlab::Access::DEVELOPER) + expect(json_response['merge_access_levels'][0]['access_level']).to eq(Gitlab::Access::MASTER) + end + + it 'protects a single branch and developers can merge' do + post api("/projects/#{project.id}/protected_branches", user), + name: branch_name, merge_access_level: 30 + + expect(response).to have_gitlab_http_status(201) + expect(json_response['name']).to eq(branch_name) + expect(json_response['push_access_levels'][0]['access_level']).to eq(Gitlab::Access::MASTER) + expect(json_response['merge_access_levels'][0]['access_level']).to eq(Gitlab::Access::DEVELOPER) + end + + it 'protects a single branch and developers can push and merge' do + post api("/projects/#{project.id}/protected_branches", user), + name: branch_name, push_access_level: 30, merge_access_level: 30 + + expect(response).to have_gitlab_http_status(201) + expect(json_response['name']).to eq(branch_name) + expect(json_response['push_access_levels'][0]['access_level']).to eq(Gitlab::Access::DEVELOPER) + expect(json_response['merge_access_levels'][0]['access_level']).to eq(Gitlab::Access::DEVELOPER) + end + + it 'protects a single branch and no one can push' do + post api("/projects/#{project.id}/protected_branches", user), + name: branch_name, push_access_level: 0 + + expect(response).to have_gitlab_http_status(201) + expect(json_response['name']).to eq(branch_name) + expect(json_response['push_access_levels'][0]['access_level']).to eq(Gitlab::Access::NO_ACCESS) + expect(json_response['merge_access_levels'][0]['access_level']).to eq(Gitlab::Access::MASTER) + end + + it 'protects a single branch and no one can merge' do + post api("/projects/#{project.id}/protected_branches", user), + name: branch_name, merge_access_level: 0 + + expect(response).to have_gitlab_http_status(201) + expect(json_response['name']).to eq(branch_name) + expect(json_response['push_access_levels'][0]['access_level']).to eq(Gitlab::Access::MASTER) + expect(json_response['merge_access_levels'][0]['access_level']).to eq(Gitlab::Access::NO_ACCESS) + end + + it 'protects a single branch and no one can push or merge' do + post api("/projects/#{project.id}/protected_branches", user), + name: branch_name, push_access_level: 0, merge_access_level: 0 + + expect(response).to have_gitlab_http_status(201) + expect(json_response['name']).to eq(branch_name) + expect(json_response['push_access_levels'][0]['access_level']).to eq(Gitlab::Access::NO_ACCESS) + expect(json_response['merge_access_levels'][0]['access_level']).to eq(Gitlab::Access::NO_ACCESS) + end + + it 'returns a 409 error if the same branch is protected twice' do + post api("/projects/#{project.id}/protected_branches", user), name: protected_name + expect(response).to have_gitlab_http_status(409) + end + + context 'when branch has a wildcard in its name' do + let(:branch_name) { 'feature/*' } + + it "protects multiple branches with a wildcard in the name" do + post api("/projects/#{project.id}/protected_branches", user), name: branch_name + + expect(response).to have_gitlab_http_status(201) + expect(json_response['name']).to eq(branch_name) + expect(json_response['push_access_levels'][0]['access_level']).to eq(Gitlab::Access::MASTER) + expect(json_response['merge_access_levels'][0]['access_level']).to eq(Gitlab::Access::MASTER) + end + end + end + + context 'when authenticated as a guest' do + before do + project.add_guest(user) + end + + it "returns a 403 error if guest" do + post api("/projects/#{project.id}/protected_branches/", user), name: branch_name + + expect(response).to have_gitlab_http_status(403) + end + end + end + + describe "DELETE /projects/:id/protected_branches/unprotect/:branch" do + before do + project.add_master(user) + end + + it "unprotects a single branch" do + delete api("/projects/#{project.id}/protected_branches/#{branch_name}", user) + + expect(response).to have_gitlab_http_status(204) + end + + it "returns 404 if branch does not exist" do + delete api("/projects/#{project.id}/protected_branches/barfoo", user) + + expect(response).to have_gitlab_http_status(404) + end + + context 'when branch has a wildcard in its name' do + let(:protected_name) { 'feature*' } + + it "unprotects a wildcard branch" do + delete api("/projects/#{project.id}/protected_branches/#{branch_name}", user) + + expect(response).to have_gitlab_http_status(204) + end + end + end +end diff --git a/spec/requests/api/runner_spec.rb b/spec/requests/api/runner_spec.rb index ca5d98c78ef..edd6516cf34 100644 --- a/spec/requests/api/runner_spec.rb +++ b/spec/requests/api/runner_spec.rb @@ -42,7 +42,7 @@ describe API::Runner do end context 'when project token is used' do - let(:project) { create(:empty_project) } + let(:project) { create(:project) } it 'creates runner' do post api('/runners'), token: project.runners_token @@ -182,7 +182,7 @@ describe API::Runner do end describe '/api/v4/jobs' do - let(:project) { create(:empty_project, shared_runners_enabled: false) } + let(:project) { create(:project, shared_runners_enabled: false) } let(:pipeline) { create(:ci_pipeline_without_jobs, project: project, ref: 'master') } let(:runner) { create(:ci_runner) } let!(:job) do diff --git a/spec/requests/api/runners_spec.rb b/spec/requests/api/runners_spec.rb index 645a5389850..3a95db030d4 100644 --- a/spec/requests/api/runners_spec.rb +++ b/spec/requests/api/runners_spec.rb @@ -5,8 +5,8 @@ describe API::Runners do let(:user) { create(:user) } let(:user2) { create(:user) } - let(:project) { create(:empty_project, creator_id: user.id) } - let(:project2) { create(:empty_project, creator_id: user.id) } + 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) } diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb index 95df3429314..48d99841385 100644 --- a/spec/requests/api/services_spec.rb +++ b/spec/requests/api/services_spec.rb @@ -4,7 +4,7 @@ describe API::Services do let(:user) { create(:user) } let(:admin) { create(:admin) } let(:user2) { create(:user) } - let(:project) { create(:empty_project, creator_id: user.id, namespace: user.namespace) } + let(:project) { create(:project, creator_id: user.id, namespace: user.namespace) } Service.available_services_names.each do |service| describe "PUT /projects/:id/services/#{service.dasherize}" do @@ -98,7 +98,7 @@ describe API::Services do end describe 'POST /projects/:id/services/:slug/trigger' do - let!(:project) { create(:empty_project) } + let!(:project) { create(:project) } describe 'Mattermost Service' do let(:service_name) { 'mattermost_slash_commands' } diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb index b71ac6c30b5..c3ed5cd8ece 100644 --- a/spec/requests/api/settings_spec.rb +++ b/spec/requests/api/settings_spec.rb @@ -11,7 +11,7 @@ describe API::Settings, 'Settings' do 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['repository_storages']).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 @@ -33,7 +33,7 @@ describe API::Settings, 'Settings' do put api("/application/settings", admin), default_projects_limit: 3, password_authentication_enabled: false, - repository_storage: 'custom', + repository_storages: ['custom'], koding_enabled: true, koding_url: 'http://koding.example.com', plantuml_enabled: true, @@ -47,7 +47,6 @@ describe API::Settings, 'Settings' do expect(response).to have_http_status(200) expect(json_response['default_projects_limit']).to eq(3) expect(json_response['password_authentication_enabled']).to be_falsey - expect(json_response['repository_storage']).to eq('custom') expect(json_response['repository_storages']).to eq(['custom']) expect(json_response['koding_enabled']).to be_truthy expect(json_response['koding_url']).to eq('http://koding.example.com') diff --git a/spec/requests/api/todos_spec.rb b/spec/requests/api/todos_spec.rb index 92533f4dfea..25d7f6dffcf 100644 --- a/spec/requests/api/todos_spec.rb +++ b/spec/requests/api/todos_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' describe API::Todos do - let(:project_1) { create(:empty_project, :test_repo) } - let(:project_2) { create(:empty_project) } + let(:project_1) { create(:project, :repository) } + let(:project_2) { create(:project) } let(:author_1) { create(:user) } let(:author_2) { create(:user) } let(:john_doe) { create(:user, username: 'john_doe') } diff --git a/spec/requests/api/triggers_spec.rb b/spec/requests/api/triggers_spec.rb index 16ddade27d9..d5c53b703dd 100644 --- a/spec/requests/api/triggers_spec.rb +++ b/spec/requests/api/triggers_spec.rb @@ -13,7 +13,7 @@ describe API::Triggers do let!(:trigger_request) { create(:ci_trigger_request, trigger: trigger, created_at: '2015-01-01 12:13:14') } describe 'POST /projects/:project_id/trigger/pipeline' do - let!(:project2) { create(:project) } + let!(:project2) { create(:project, :repository) } let(:options) do { token: trigger_token @@ -22,6 +22,7 @@ describe API::Triggers do before do stub_ci_pipeline_to_return_yaml_file + trigger.update(owner: user) end context 'Handles errors' do @@ -36,12 +37,6 @@ describe API::Triggers do expect(response).to have_http_status(404) end - - it 'returns unauthorized if token is for different project' do - post api("/projects/#{project2.id}/trigger/pipeline"), options.merge(ref: 'master') - - expect(response).to have_http_status(401) - end end context 'Have a commit' do @@ -61,7 +56,7 @@ describe API::Triggers do post api("/projects/#{project.id}/trigger/pipeline"), options.merge(ref: 'other-branch') expect(response).to have_http_status(400) - expect(json_response['message']).to eq('No pipeline created') + expect(json_response['message']).to eq('base' => ["Reference not found"]) end context 'Validates variables' do @@ -87,12 +82,18 @@ describe API::Triggers do post api("/projects/#{project.id}/trigger/pipeline"), options.merge(variables: variables, ref: 'master') expect(response).to have_http_status(201) - expect(pipeline.builds.reload.first.trigger_request.variables).to eq(variables) + expect(pipeline.variables.map { |v| { v.key => v.value } }.last).to eq(variables) end end end context 'when triggering a pipeline from a trigger token' do + it 'does not leak the presence of project when token is for different project' do + post api("/projects/#{project2.id}/ref/master/trigger/pipeline?token=#{trigger_token}"), { ref: 'refs/heads/other-branch' } + + expect(response).to have_http_status(404) + end + it 'creates builds from the ref given in the URL, not in the body' do expect do post api("/projects/#{project.id}/ref/master/trigger/pipeline?token=#{trigger_token}"), { ref: 'refs/heads/other-branch' } diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index 877bde3b9a6..2dc7be22f8f 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -16,38 +16,44 @@ describe API::Users do it "returns authorization error when the `username` parameter is not passed" do get api("/users") - expect(response).to have_http_status(403) + expect(response).to have_gitlab_http_status(403) end it "returns the user when a valid `username` parameter is passed" do - user = create(:user) - get api("/users"), username: user.username - expect(response).to have_http_status(200) + 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[0]['id']).to eq(user.id) expect(json_response[0]['username']).to eq(user.username) end - it "returns authorization error when the `username` parameter refers to an inaccessible user" do - user = create(:user) - - stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC]) - - get api("/users"), username: user.username - - expect(response).to have_http_status(403) - end - it "returns an empty response when an invalid `username` parameter is passed" do get api("/users"), username: 'invalid' - expect(response).to have_http_status(200) + expect(response).to have_gitlab_http_status(200) expect(json_response).to be_an Array expect(json_response.size).to eq(0) end + + context "when public level is restricted" do + before do + stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC]) + end + + it "returns authorization error when the `username` parameter refers to an inaccessible user" do + get api("/users"), username: user.username + + expect(response).to have_gitlab_http_status(403) + end + + it "returns authorization error when the `username` parameter is not passed" do + get api("/users") + + expect(response).to have_gitlab_http_status(403) + end + end end context "when authenticated" do @@ -55,17 +61,22 @@ describe API::Users do context "when public level is restricted" do before do stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC]) - allow_any_instance_of(API::Helpers).to receive(:authenticate!).and_return(true) end - it "renders 403" do - get api("/users") - expect(response).to have_http_status(403) + context 'when authenticate as a regular user' do + it "renders 200" do + get api("/users", user) + + expect(response).to have_gitlab_http_status(200) + end end - it "renders 404" do - get api("/users/#{user.id}") - expect(response).to have_http_status(404) + context 'when authenticate as an admin' do + it "renders 200" do + get api("/users", admin) + + expect(response).to have_gitlab_http_status(200) + end end end diff --git a/spec/requests/api/v3/award_emoji_spec.rb b/spec/requests/api/v3/award_emoji_spec.rb index 9234710f488..681e8e04295 100644 --- a/spec/requests/api/v3/award_emoji_spec.rb +++ b/spec/requests/api/v3/award_emoji_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe API::V3::AwardEmoji do let(:user) { create(:user) } - let!(:project) { create(:empty_project) } + let!(:project) { create(:project) } let(:issue) { create(:issue, project: project) } let!(:award_emoji) { create(:award_emoji, awardable: issue, user: user) } let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) } diff --git a/spec/requests/api/v3/boards_spec.rb b/spec/requests/api/v3/boards_spec.rb index 4d786331d1b..b86aab2ec70 100644 --- a/spec/requests/api/v3/boards_spec.rb +++ b/spec/requests/api/v3/boards_spec.rb @@ -4,7 +4,7 @@ describe API::V3::Boards do let(:user) { create(:user) } let(:guest) { create(:user) } let(:non_member) { create(:user) } - let!(:project) { create(:empty_project, :public, creator_id: user.id, namespace: user.namespace ) } + let!(:project) { create(:project, :public, creator_id: user.id, namespace: user.namespace ) } let!(:dev_label) do create(:label, title: 'Development', color: '#FFAABB', project: project) @@ -99,7 +99,7 @@ describe API::V3::Boards do context "when the user is project owner" do let(:owner) { create(:user) } - let(:project) { create(:empty_project, namespace: owner.namespace) } + let(:project) { create(:project, namespace: owner.namespace) } it "deletes the list if an admin requests it" do delete v3_api("#{base_url}/#{dev_list.id}", owner) diff --git a/spec/requests/api/v3/deploy_keys_spec.rb b/spec/requests/api/v3/deploy_keys_spec.rb index 94f4d93a8dc..13a62423b1d 100644 --- a/spec/requests/api/v3/deploy_keys_spec.rb +++ b/spec/requests/api/v3/deploy_keys_spec.rb @@ -3,8 +3,8 @@ require 'spec_helper' describe API::V3::DeployKeys do let(:user) { create(:user) } let(:admin) { create(:admin) } - let(:project) { create(:empty_project, creator_id: user.id) } - let(:project2) { create(:empty_project, creator_id: user.id) } + 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 @@ -133,7 +133,7 @@ describe API::V3::DeployKeys do end describe "POST /projects/:id/#{path}/:key_id/enable" do - let(:project2) { create(:empty_project) } + let(:project2) { create(:project) } context 'when the user can admin the project' do it 'enables the key' do diff --git a/spec/requests/api/v3/environments_spec.rb b/spec/requests/api/v3/environments_spec.rb index 99f35723974..39264e819a3 100644 --- a/spec/requests/api/v3/environments_spec.rb +++ b/spec/requests/api/v3/environments_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe API::V3::Environments do let(:user) { create(:user) } let(:non_member) { create(:user) } - let(:project) { create(:empty_project, :private, namespace: user.namespace) } + let(:project) { create(:project, :private, namespace: user.namespace) } let!(:environment) { create(:environment, project: project) } before do diff --git a/spec/requests/api/v3/files_spec.rb b/spec/requests/api/v3/files_spec.rb index 8b2d165c763..4ffa5d1784e 100644 --- a/spec/requests/api/v3/files_spec.rb +++ b/spec/requests/api/v3/files_spec.rb @@ -74,7 +74,7 @@ describe API::V3::Files do context 'when unauthenticated', 'and project is public' do it_behaves_like 'repository files' do - let(:project) { create(:project, :public) } + let(:project) { create(:project, :public, :repository) } let(:current_user) { nil } end end diff --git a/spec/requests/api/v3/groups_spec.rb b/spec/requests/api/v3/groups_spec.rb index 63c5707b2e4..10756e494c3 100644 --- a/spec/requests/api/v3/groups_spec.rb +++ b/spec/requests/api/v3/groups_spec.rb @@ -9,9 +9,9 @@ describe API::V3::Groups do let(:admin) { create(:admin) } let!(:group1) { create(:group, avatar: File.open(uploaded_image_temp_path)) } let!(:group2) { create(:group, :private) } - let!(:project1) { create(:empty_project, namespace: group1) } - let!(:project2) { create(:empty_project, namespace: group2) } - let!(:project3) { create(:empty_project, namespace: group1, path: 'test', visibility_level: Gitlab::VisibilityLevel::PRIVATE) } + 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) @@ -165,7 +165,7 @@ describe API::V3::Groups do describe "GET /groups/:id" do context "when authenticated as user" do it "returns one of user1's groups" do - project = create(:empty_project, namespace: group2, path: 'Foo') + project = create(:project, namespace: group2, path: 'Foo') create(:project_group_link, project: project, group: group1) get v3_api("/groups/#{group1.id}", user1) @@ -307,7 +307,7 @@ describe API::V3::Groups do end it 'filters the groups projects' do - public_project = create(:empty_project, :public, path: 'test1', group: group1) + public_project = create(:project, :public, path: 'test1', group: group1) get v3_api("/groups/#{group1.id}/projects", user1), visibility: 'public' @@ -501,8 +501,8 @@ describe API::V3::Groups do end describe "POST /groups/:id/projects/:project_id" do - let(:project) { create(:empty_project) } - let(:project_path) { "#{project.namespace.path}%2F#{project.path}" } + let(:project) { create(:project) } + let(:project_path) { CGI.escape(project.full_path) } before(:each) do allow_any_instance_of(Projects::TransferService) diff --git a/spec/requests/api/v3/issues_spec.rb b/spec/requests/api/v3/issues_spec.rb index cc81922697a..9eb538c4b09 100644 --- a/spec/requests/api/v3/issues_spec.rb +++ b/spec/requests/api/v3/issues_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::V3::Issues do - include EmailHelpers - +describe API::V3::Issues, :mailer do let(:user) { create(:user) } let(:user2) { create(:user) } let(:non_member) { create(:user) } @@ -10,7 +8,7 @@ describe API::V3::Issues do let(:author) { create(:author) } let(:assignee) { create(:assignee) } let(:admin) { create(:user, :admin) } - let!(:project) { create(:empty_project, :public, creator_id: user.id, namespace: user.namespace ) } + let!(:project) { create(:project, :public, creator_id: user.id, namespace: user.namespace ) } let!(:closed_issue) do create :closed_issue, author: user, @@ -243,7 +241,7 @@ describe API::V3::Issues do describe "GET /groups/:id/issues" do let!(:group) { create(:group) } - let!(:group_project) { create(:empty_project, :public, creator_id: user.id, namespace: group) } + let!(:group_project) { create(:project, :public, creator_id: user.id, namespace: group) } let!(:group_closed_issue) do create :closed_issue, author: user, @@ -453,7 +451,7 @@ describe API::V3::Issues do end it "returns 404 on private projects for other users" do - private_project = create(:empty_project, :private) + private_project = create(:project, :private) create(:issue, project: private_project) get v3_api("/projects/#{private_project.id}/issues", non_member) @@ -462,7 +460,7 @@ describe API::V3::Issues do end it 'returns no issues when user has access to project but not issues' do - restricted_project = create(:empty_project, :public, issues_access_level: ProjectFeature::PRIVATE) + 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) @@ -1114,7 +1112,7 @@ describe API::V3::Issues do put v3_api("/projects/#{project.id}/issues/#{closed_issue.id}", user), state_event: 'reopen' expect(response).to have_http_status(200) - expect(json_response['state']).to eq 'reopened' + expect(json_response['state']).to eq 'opened' end context 'when an admin or owner makes the request' do @@ -1172,7 +1170,7 @@ describe API::V3::Issues do context "when the user is project owner" do let(:owner) { create(:user) } - let(:project) { create(:empty_project, namespace: owner.namespace) } + 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) @@ -1192,8 +1190,8 @@ describe API::V3::Issues do end describe '/projects/:id/issues/:issue_id/move' do - let!(:target_project) { create(:empty_project, path: 'project2', creator_id: user.id, namespace: user.namespace ) } - let!(:target_project2) { create(:empty_project, creator_id: non_member.id, namespace: non_member.namespace ) } + let!(:target_project) { create(:project, path: 'project2', 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), diff --git a/spec/requests/api/v3/labels_spec.rb b/spec/requests/api/v3/labels_spec.rb index 62faa1cb129..32f37a08024 100644 --- a/spec/requests/api/v3/labels_spec.rb +++ b/spec/requests/api/v3/labels_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe API::V3::Labels do let(:user) { create(:user) } - let(:project) { create(:empty_project, creator_id: user.id, namespace: user.namespace) } + 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) } diff --git a/spec/requests/api/v3/members_spec.rb b/spec/requests/api/v3/members_spec.rb index 623f02902b8..bc918a8eb02 100644 --- a/spec/requests/api/v3/members_spec.rb +++ b/spec/requests/api/v3/members_spec.rb @@ -7,7 +7,7 @@ describe API::V3::Members do let(:stranger) { create(:user) } let(:project) do - create(:empty_project, :public, :access_requestable, creator_id: master.id, namespace: master.namespace) do |project| + create(:project, :public, :access_requestable, creator_id: master.id, namespace: master.namespace) do |project| project.team << [developer, :developer] project.team << [master, :master] project.request_access(access_requester) diff --git a/spec/requests/api/v3/merge_requests_spec.rb b/spec/requests/api/v3/merge_requests_spec.rb index 4f9e63f2ace..ef7516fc28f 100644 --- a/spec/requests/api/v3/merge_requests_spec.rb +++ b/spec/requests/api/v3/merge_requests_spec.rb @@ -312,8 +312,8 @@ describe API::MergeRequests do context 'forked projects' do let!(:user2) { create(:user) } - let!(:fork_project) { create(:empty_project, forked_from_project: project, namespace: user2.namespace, creator_id: user2.id) } - let!(:unrelated_project) { create(:empty_project, namespace: create(:user).namespace, creator_id: user2.id) } + let!(:fork_project) { create(:project, forked_from_project: project, namespace: user2.namespace, creator_id: user2.id) } + let!(:unrelated_project) { create(:project, namespace: create(:user).namespace, creator_id: user2.id) } before :each do |each| fork_project.team << [user2, :reporter] @@ -635,7 +635,7 @@ describe API::MergeRequests do end it 'handles external issues' do - jira_project = create(:jira_project, :public, name: 'JIR_EXT1') + 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)}") @@ -650,7 +650,7 @@ describe API::MergeRequests do end it 'returns 403 if the user has no access to the merge request' do - project = create(:empty_project, :private) + project = create(:project, :private, :repository) merge_request = create(:merge_request, :simple, source_project: project) guest = create(:user) project.team << [guest, :guest] diff --git a/spec/requests/api/v3/milestones_spec.rb b/spec/requests/api/v3/milestones_spec.rb index f04efc990a7..feaa87faec7 100644 --- a/spec/requests/api/v3/milestones_spec.rb +++ b/spec/requests/api/v3/milestones_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe API::V3::Milestones do let(:user) { create(:user) } - let!(:project) { create(:empty_project, namespace: user.namespace ) } + let!(:project) { create(:project, namespace: user.namespace ) } let!(:closed_milestone) { create(:closed_milestone, project: project) } let!(:milestone) { create(:milestone, project: project) } @@ -194,7 +194,7 @@ describe API::V3::Milestones do end describe 'confidential issues' do - let(:public_project) { create(:empty_project, :public) } + 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) } diff --git a/spec/requests/api/v3/notes_spec.rb b/spec/requests/api/v3/notes_spec.rb index b5f98a9a545..56729692eed 100644 --- a/spec/requests/api/v3/notes_spec.rb +++ b/spec/requests/api/v3/notes_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe API::V3::Notes do let(:user) { create(:user) } - let!(:project) { create(:empty_project, :public, namespace: user.namespace) } + 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) } @@ -13,12 +13,12 @@ describe API::V3::Notes do # For testing the cross-reference of a private issue in a public issue let(:private_user) { create(:user) } let(:private_project) do - create(:empty_project, namespace: private_user.namespace) + create(:project, namespace: private_user.namespace) .tap { |p| p.team << [private_user, :master] } end let(:private_issue) { create(:issue, project: private_project) } - let(:ext_proj) { create(:empty_project, :public) } + let(:ext_proj) { create(:project, :public) } let(:ext_issue) { create(:issue, project: ext_proj) } let!(:cross_reference_note) do @@ -268,7 +268,7 @@ describe API::V3::Notes do context 'when user does not have access to read the noteable' do it 'responds with 404' do - project = create(:empty_project, :private) { |p| p.add_guest(user) } + 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), @@ -279,7 +279,7 @@ describe API::V3::Notes do end context 'when user does not have access to create noteable' do - let(:private_issue) { create(:issue, project: create(:empty_project, :private)) } + let(:private_issue) { create(:issue, project: create(:project, :private)) } ## # We are posting to project user has access to, but we use issue id diff --git a/spec/requests/api/v3/project_hooks_spec.rb b/spec/requests/api/v3/project_hooks_spec.rb index 1969d1c7f2b..b0eddbb5dd2 100644 --- a/spec/requests/api/v3/project_hooks_spec.rb +++ b/spec/requests/api/v3/project_hooks_spec.rb @@ -87,7 +87,7 @@ describe API::ProjectHooks, 'ProjectHooks' do it "adds hook to project" do expect do post v3_api("/projects/#{project.id}/hooks", user), - url: "http://example.com", issues_events: true, wiki_page_events: true + url: "http://example.com", issues_events: true, wiki_page_events: true, build_events: true end.to change {project.hooks.count}.by(1) expect(response).to have_http_status(201) @@ -97,7 +97,7 @@ describe API::ProjectHooks, 'ProjectHooks' do 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(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) @@ -135,7 +135,7 @@ describe API::ProjectHooks, 'ProjectHooks' do 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 + url: 'http://example.org', push_events: false, build_events: true expect(response).to have_http_status(200) expect(json_response['url']).to eq('http://example.org') expect(json_response['issues_events']).to eq(hook.issues_events) diff --git a/spec/requests/api/v3/project_snippets_spec.rb b/spec/requests/api/v3/project_snippets_spec.rb index 1950c64c690..758fb482374 100644 --- a/spec/requests/api/v3/project_snippets_spec.rb +++ b/spec/requests/api/v3/project_snippets_spec.rb @@ -1,7 +1,7 @@ require 'rails_helper' describe API::ProjectSnippets do - let(:project) { create(:empty_project, :public) } + let(:project) { create(:project, :public) } let(:user) { create(:user) } let(:admin) { create(:admin) } diff --git a/spec/requests/api/v3/projects_spec.rb b/spec/requests/api/v3/projects_spec.rb index af44ffa2331..c211cc20e53 100644 --- a/spec/requests/api/v3/projects_spec.rb +++ b/spec/requests/api/v3/projects_spec.rb @@ -7,8 +7,8 @@ describe API::V3::Projects do let(:user2) { create(:user) } let(:user3) { create(:user) } let(:admin) { create(:admin) } - let(:project) { create(:empty_project, creator_id: user.id, namespace: user.namespace) } - let(:project2) { create(:empty_project, path: 'project2', creator_id: user.id, namespace: user.namespace) } + let(:project) { create(:project, creator_id: user.id, namespace: user.namespace) } + let(:project2) { create(:project, path: 'project2', 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) } @@ -31,7 +31,7 @@ describe API::V3::Projects do access_level: ProjectMember::MASTER) end let(:project4) do - create(:empty_project, + create(:project, name: 'third_project', path: 'third_project', creator_id: user4.id, @@ -125,7 +125,7 @@ describe API::V3::Projects do end context 'and using archived' do - let!(:archived_project) { create(:empty_project, creator_id: user.id, namespace: user.namespace, archived: true) } + 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) @@ -281,7 +281,7 @@ describe API::V3::Projects do end end - let!(:public_project) { create(:empty_project, :public) } + let!(:public_project) { create(:project, :public) } before do project project2 @@ -312,7 +312,7 @@ describe API::V3::Projects do end describe 'GET /projects/starred' do - let(:public_project) { create(:empty_project, :public) } + let(:public_project) { create(:project, :public) } before do project_member @@ -637,7 +637,7 @@ describe API::V3::Projects do describe 'GET /projects/:id' do context 'when unauthenticated' do it 'returns the public projects' do - public_project = create(:empty_project, :public) + public_project = create(:project, :public) get v3_api("/projects/#{public_project.id}") @@ -718,9 +718,9 @@ describe API::V3::Projects do it 'handles users with dots' do dot_user = create(:user, username: 'dot.user') - project = create(:empty_project, creator_id: dot_user.id, namespace: dot_user.namespace) + project = create(:project, creator_id: dot_user.id, namespace: dot_user.namespace) - get v3_api("/projects/#{dot_user.namespace.name}%2F#{project.path}", dot_user) + get v3_api("/projects/#{CGI.escape(project.full_path)}", dot_user) expect(response).to have_http_status(200) expect(json_response['name']).to eq(project.name) end @@ -766,7 +766,7 @@ describe API::V3::Projects do end context 'group project' do - let(:project2) { create(:empty_project, group: create(:group)) } + let(:project2) { create(:project, group: create(:group)) } before { project2.group.add_owner(user) } @@ -811,7 +811,7 @@ describe API::V3::Projects do context 'when unauthenticated' do it_behaves_like 'project events response' do - let(:project) { create(:empty_project, :public) } + let(:project) { create(:project, :public) } let(:current_user) { nil } end end @@ -861,7 +861,7 @@ describe API::V3::Projects do context 'when unauthenticated' do it_behaves_like 'project users response' do - let(:project) { create(:empty_project, :public) } + let(:project) { create(:project, :public) } let(:current_user) { nil } end end @@ -975,11 +975,11 @@ describe API::V3::Projects do end describe 'fork management' do - let(:project_fork_target) { create(:empty_project) } - let(:project_fork_source) { create(:empty_project, :public) } + 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(:empty_project, :public) } + 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) @@ -1020,7 +1020,7 @@ describe API::V3::Projects do end context 'when users belong to project group' do - let(:project_fork_target) { create(:empty_project, group: create(:group)) } + let(:project_fork_target) { create(:project, group: create(:group)) } before do project_fork_target.group.add_owner user @@ -1140,16 +1140,16 @@ describe API::V3::Projects do describe 'GET /projects/search/:query' do let!(:query) { 'query'} - let!(:search) { create(:empty_project, name: query, creator_id: user.id, namespace: user.namespace) } - let!(:pre) { create(:empty_project, name: "pre_#{query}", creator_id: user.id, namespace: user.namespace) } - let!(:post) { create(:empty_project, name: "#{query}_post", creator_id: user.id, namespace: user.namespace) } - let!(:pre_post) { create(:empty_project, name: "pre_#{query}_post", creator_id: user.id, namespace: user.namespace) } - let!(:unfound) { create(:empty_project, name: 'unfound', creator_id: user.id, namespace: user.namespace) } - let!(:internal) { create(:empty_project, :internal, name: "internal #{query}") } - let!(:unfound_internal) { create(:empty_project, :internal, name: 'unfound internal') } - let!(:public) { create(:empty_project, :public, name: "public #{query}") } - let!(:unfound_public) { create(:empty_project, :public, name: 'unfound public') } - let!(:one_dot_two) { create(:empty_project, :public, name: "one.dot.two") } + 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 diff --git a/spec/requests/api/v3/runners_spec.rb b/spec/requests/api/v3/runners_spec.rb index dbda2cf34c3..78660afd840 100644 --- a/spec/requests/api/v3/runners_spec.rb +++ b/spec/requests/api/v3/runners_spec.rb @@ -5,8 +5,8 @@ describe API::V3::Runners do let(:user) { create(:user) } let(:user2) { create(:user) } - let(:project) { create(:empty_project, creator_id: user.id) } - let(:project2) { create(:empty_project, creator_id: user.id) } + 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) } diff --git a/spec/requests/api/v3/services_spec.rb b/spec/requests/api/v3/services_spec.rb index 3ba62de822a..f0fa48e22df 100644 --- a/spec/requests/api/v3/services_spec.rb +++ b/spec/requests/api/v3/services_spec.rb @@ -2,7 +2,7 @@ require "spec_helper" describe API::V3::Services do let(:user) { create(:user) } - let(:project) { create(:empty_project, creator_id: user.id, namespace: user.namespace) } + let(:project) { create(:project, creator_id: user.id, namespace: user.namespace) } available_services = Service.available_services_names available_services.delete('prometheus') diff --git a/spec/requests/api/v3/todos_spec.rb b/spec/requests/api/v3/todos_spec.rb index 9c2c4d64257..8f5c3fbf8dd 100644 --- a/spec/requests/api/v3/todos_spec.rb +++ b/spec/requests/api/v3/todos_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' describe API::V3::Todos do - let(:project_1) { create(:empty_project) } - let(:project_2) { create(:empty_project) } + 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') } diff --git a/spec/requests/api/v3/triggers_spec.rb b/spec/requests/api/v3/triggers_spec.rb index d3de6bf13bc..60212660fb6 100644 --- a/spec/requests/api/v3/triggers_spec.rb +++ b/spec/requests/api/v3/triggers_spec.rb @@ -52,7 +52,8 @@ describe API::V3::Triggers do 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_http_status(400) - expect(json_response['message']).to eq('No builds created') + expect(json_response['message']['base']) + .to contain_exactly('Reference not found') end context 'Validates variables' do diff --git a/spec/requests/api/v3/users_spec.rb b/spec/requests/api/v3/users_spec.rb index de7499a4e43..bc0a4ab20a3 100644 --- a/spec/requests/api/v3/users_spec.rb +++ b/spec/requests/api/v3/users_spec.rb @@ -232,7 +232,7 @@ describe API::V3::Users do describe 'GET /users/:id/events' do let(:user) { create(:user) } - let(:project) { create(:empty_project) } + let(:project) { create(:project) } let(:note) { create(:note_on_issue, note: 'What an awesome day!', project: project) } before do @@ -276,7 +276,7 @@ describe API::V3::Users do end context 'when there are multiple events from different projects' do - let(:second_note) { create(:note_on_issue, project: create(:empty_project)) } + let(:second_note) { create(:note_on_issue, project: create(:project)) } let(:third_note) { create(:note_on_issue, project: project) } before do diff --git a/spec/requests/api/variables_spec.rb b/spec/requests/api/variables_spec.rb index e0975024b80..098a0d8ca7d 100644 --- a/spec/requests/api/variables_spec.rb +++ b/spec/requests/api/variables_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe API::Variables do let(:user) { create(:user) } let(:user2) { create(:user) } - let!(:project) { create(:empty_project, creator_id: user.id) } + let!(:project) { create(:project, creator_id: user.id) } let!(:master) { create(:project_member, :master, user: user, project: project) } let!(:developer) { create(:project_member, :developer, user: user2, project: project) } let!(:variable) { create(:ci_variable, project: project) } diff --git a/spec/requests/ci/api/builds_spec.rb b/spec/requests/ci/api/builds_spec.rb index 49e815ee16c..c077c458163 100644 --- a/spec/requests/ci/api/builds_spec.rb +++ b/spec/requests/ci/api/builds_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe Ci::API::Builds do let(:runner) { FactoryGirl.create(:ci_runner, tag_list: %w(mysql ruby)) } - let(:project) { FactoryGirl.create(:empty_project, shared_runners_enabled: false) } + let(:project) { FactoryGirl.create(:project, shared_runners_enabled: false) } let(:last_update) { nil } describe "Builds API for runners" do diff --git a/spec/requests/ci/api/runners_spec.rb b/spec/requests/ci/api/runners_spec.rb index 78b2be350cd..75059dd20a0 100644 --- a/spec/requests/ci/api/runners_spec.rb +++ b/spec/requests/ci/api/runners_spec.rb @@ -70,7 +70,7 @@ describe Ci::API::Runners do end context 'when project token is provided' do - let(:project) { FactoryGirl.create(:empty_project) } + let(:project) { FactoryGirl.create(:project) } before do post ci_api("/runners/register"), token: project.runners_token diff --git a/spec/requests/ci/api/triggers_spec.rb b/spec/requests/ci/api/triggers_spec.rb index 26b03c0f148..7c77ebb69a2 100644 --- a/spec/requests/ci/api/triggers_spec.rb +++ b/spec/requests/ci/api/triggers_spec.rb @@ -4,8 +4,15 @@ describe Ci::API::Triggers do describe 'POST /projects/:project_id/refs/:ref/trigger' do let!(:trigger_token) { 'secure token' } let!(:project) { create(:project, :repository, ci_id: 10) } - let!(:project2) { create(:empty_project, ci_id: 11) } - let!(:trigger) { create(:ci_trigger, project: project, token: trigger_token) } + let!(:project2) { create(:project, ci_id: 11) } + + let!(:trigger) do + create(:ci_trigger, + project: project, + token: trigger_token, + owner: create(:user)) + end + let(:options) do { token: trigger_token @@ -14,6 +21,8 @@ describe Ci::API::Triggers do before do stub_ci_pipeline_to_return_yaml_file + + project.add_developer(trigger.owner) end context 'Handles errors' do @@ -47,7 +56,8 @@ describe Ci::API::Triggers do it 'returns bad request with no builds created if there\'s no commit for that ref' do post ci_api("/projects/#{project.ci_id}/refs/other-branch/trigger"), options expect(response).to have_http_status(400) - expect(json_response['message']).to eq('No builds created') + expect(json_response['message']['base']) + .to contain_exactly('Reference not found') end context 'Validates variables' do diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb index d043ab2a974..ecac40e301b 100644 --- a/spec/requests/git_http_spec.rb +++ b/spec/requests/git_http_spec.rb @@ -1,6 +1,6 @@ require "spec_helper" -describe 'Git HTTP requests', lib: true do +describe 'Git HTTP requests' do include GitHttpHelpers include WorkhorseHelpers include UserActivitiesHelpers @@ -123,7 +123,7 @@ describe 'Git HTTP requests', lib: true do context "when requesting the Wiki" do let(:wiki) { ProjectWiki.new(project) } - let(:path) { "/#{wiki.repository.path_with_namespace}.git" } + let(:path) { "/#{wiki.repository.full_path}.git" } context "when the project is public" do let(:project) { create(:project, :repository, :public, :wiki_enabled) } @@ -139,7 +139,7 @@ describe 'Git HTTP requests', lib: true do download(path) do |response| json_body = ActiveSupport::JSON.decode(response.body) - expect(json_body['RepoPath']).to include(wiki.repository.path_with_namespace) + expect(json_body['RepoPath']).to include(wiki.repository.full_path) end end end @@ -222,7 +222,7 @@ describe 'Git HTTP requests', lib: true do end context "when the project exists" do - let(:path) { "#{project.path_with_namespace}.git" } + let(:path) { "#{project.full_path}.git" } context "when the project is public" do let(:project) { create(:project, :repository, :public) } @@ -286,7 +286,7 @@ describe 'Git HTTP requests', lib: true do context 'when the request is not from gitlab-workhorse' do it 'raises an exception' do expect do - get("/#{project.path_with_namespace}.git/info/refs?service=git-upload-pack") + get("/#{project.full_path}.git/info/refs?service=git-upload-pack") end.to raise_error(JWT::DecodeError) end end @@ -294,7 +294,7 @@ describe 'Git HTTP requests', lib: true do context 'when the repo is public' do context 'but the repo is disabled' do let(:project) { create(:project, :public, :repository, :repository_disabled) } - let(:path) { "#{project.path_with_namespace}.git" } + let(:path) { "#{project.full_path}.git" } let(:env) { {} } it_behaves_like 'pulls require Basic HTTP Authentication' @@ -303,7 +303,7 @@ describe 'Git HTTP requests', lib: true do context 'but the repo is enabled' do let(:project) { create(:project, :public, :repository, :repository_enabled) } - let(:path) { "#{project.path_with_namespace}.git" } + let(:path) { "#{project.full_path}.git" } let(:env) { {} } it_behaves_like 'pulls are allowed' @@ -421,7 +421,7 @@ describe 'Git HTTP requests', lib: true do @token = Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id, scopes: "api") end - let(:path) { "#{project.path_with_namespace}.git" } + let(:path) { "#{project.full_path}.git" } let(:env) { { user: 'oauth2', password: @token.token } } it_behaves_like 'pulls are allowed' @@ -431,7 +431,7 @@ describe 'Git HTTP requests', lib: true do context 'when user has 2FA enabled' do let(:user) { create(:user, :two_factor) } let(:access_token) { create(:personal_access_token, user: user) } - let(:path) { "#{project.path_with_namespace}.git" } + let(:path) { "#{project.full_path}.git" } before do project.team << [user, :master] @@ -573,14 +573,14 @@ describe 'Git HTTP requests', lib: true do context "when a gitlab ci token is provided" do let(:project) { create(:project, :repository) } let(:build) { create(:ci_build, :running) } - let(:other_project) { create(:empty_project) } + let(:other_project) { create(:project) } before do build.update!(project: project) # can't associate it on factory create end context 'when build created by system is authenticated' do - let(:path) { "#{project.path_with_namespace}.git" } + let(:path) { "#{project.full_path}.git" } let(:env) { { user: 'gitlab-ci-token', password: build.token } } it_behaves_like 'pulls are allowed' @@ -602,7 +602,7 @@ describe 'Git HTTP requests', lib: true do # We are "authenticated" as CI using a valid token here. But we are # not authorized to see any other project, so return "not found". it "rejects pulls for other project with 404 Not Found" do - clone_get("#{other_project.path_with_namespace}.git", env) + clone_get("#{other_project.full_path}.git", env) expect(response).to have_http_status(:not_found) expect(response.body).to eq(git_access_error(:project_not_found)) @@ -616,13 +616,13 @@ describe 'Git HTTP requests', lib: true do end shared_examples 'can download code only' do - let(:path) { "#{project.path_with_namespace}.git" } + let(:path) { "#{project.full_path}.git" } let(:env) { { user: 'gitlab-ci-token', password: build.token } } it_behaves_like 'pulls are allowed' context 'when the repo does not exist' do - let(:project) { create(:empty_project) } + let(:project) { create(:project) } it 'rejects pulls with 403 Forbidden' do clone_get path, env @@ -646,7 +646,7 @@ describe 'Git HTTP requests', lib: true do it_behaves_like 'can download code only' it 'downloads from other project get status 403' do - clone_get "#{other_project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token + clone_get "#{other_project.full_path}.git", user: 'gitlab-ci-token', password: build.token expect(response).to have_http_status(:forbidden) end @@ -658,7 +658,7 @@ describe 'Git HTTP requests', lib: true do it_behaves_like 'can download code only' it 'downloads from other project get status 404' do - clone_get "#{other_project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token + clone_get "#{other_project.full_path}.git", user: 'gitlab-ci-token', password: build.token expect(response).to have_http_status(:not_found) end @@ -671,7 +671,7 @@ describe 'Git HTTP requests', lib: true do let(:project) { create(:project, :repository, :public, path: 'project.git-project') } context "GET info/refs" do - let(:path) { "/#{project.path_with_namespace}/info/refs" } + let(:path) { "/#{project.full_path}/info/refs" } context "when no params are added" do before do @@ -679,7 +679,7 @@ describe 'Git HTTP requests', lib: true do end it "redirects to the .git suffix version" do - expect(response).to redirect_to("/#{project.path_with_namespace}.git/info/refs") + expect(response).to redirect_to("/#{project.full_path}.git/info/refs") end end @@ -691,7 +691,7 @@ describe 'Git HTTP requests', lib: true do end it "redirects to the .git suffix version" do - expect(response).to redirect_to("/#{project.path_with_namespace}.git/info/refs?service=#{params[:service]}") + expect(response).to redirect_to("/#{project.full_path}.git/info/refs?service=#{params[:service]}") end end @@ -703,7 +703,7 @@ describe 'Git HTTP requests', lib: true do end it "redirects to the .git suffix version" do - expect(response).to redirect_to("/#{project.path_with_namespace}.git/info/refs?service=#{params[:service]}") + expect(response).to redirect_to("/#{project.full_path}.git/info/refs?service=#{params[:service]}") end end @@ -722,13 +722,13 @@ describe 'Git HTTP requests', lib: true do context "POST git-upload-pack" do it "fails to find a route" do - expect { clone_post(project.path_with_namespace) }.to raise_error(ActionController::RoutingError) + expect { clone_post(project.full_path) }.to raise_error(ActionController::RoutingError) end end context "POST git-receive-pack" do it "fails to find a route" do - expect { push_post(project.path_with_namespace) }.to raise_error(ActionController::RoutingError) + expect { push_post(project.full_path) }.to raise_error(ActionController::RoutingError) end end end @@ -744,7 +744,7 @@ describe 'Git HTTP requests', lib: true do Blob.decorate(Gitlab::Git::Blob.find(project.repository, 'master', 'bar/branch-test.txt'), project) end - get "/#{project.path_with_namespace}/blob/master/info/refs" + get "/#{project.full_path}/blob/master/info/refs" end it "returns the file" do @@ -754,7 +754,7 @@ describe 'Git HTTP requests', lib: true do context "when the file does not exist" do before do - get "/#{project.path_with_namespace}/blob/master/info/refs" + get "/#{project.full_path}/blob/master/info/refs" end it "returns not found" do diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb index 697b150ab34..27d09b8202e 100644 --- a/spec/requests/lfs_http_spec.rb +++ b/spec/requests/lfs_http_spec.rb @@ -20,7 +20,7 @@ describe 'Git LFS API and storage' do let(:sample_size) { lfs_object.size } describe 'when lfs is disabled' do - let(:project) { create(:empty_project) } + let(:project) { create(:project) } let(:body) do { 'objects' => [ @@ -46,7 +46,7 @@ describe 'Git LFS API and storage' do end context 'project specific LFS settings' do - let(:project) { create(:empty_project) } + let(:project) { create(:project) } let(:body) do { 'objects' => [ @@ -151,7 +151,7 @@ describe 'Git LFS API and storage' do end describe 'deprecated API' do - let(:project) { create(:empty_project) } + let(:project) { create(:project) } before do enable_lfs @@ -188,7 +188,7 @@ describe 'Git LFS API and storage' do end describe 'when fetching lfs object' do - let(:project) { create(:empty_project) } + let(:project) { create(:project) } let(:update_permissions) { } before do @@ -281,7 +281,7 @@ describe 'Git LFS API and storage' do shared_examples 'can download LFS only from own projects' do context 'for owned project' do - let(:project) { create(:empty_project, namespace: user.namespace) } + let(:project) { create(:project, namespace: user.namespace) } let(:update_permissions) do project.lfs_objects << lfs_object @@ -302,7 +302,7 @@ describe 'Git LFS API and storage' do end context 'for other project' do - let(:other_project) { create(:empty_project) } + let(:other_project) { create(:project) } let(:pipeline) { create(:ci_empty_pipeline, project: other_project) } let(:update_permissions) do @@ -368,7 +368,7 @@ describe 'Git LFS API and storage' do end describe 'download' do - let(:project) { create(:empty_project) } + let(:project) { create(:project) } let(:body) do { 'operation' => 'download', @@ -408,7 +408,7 @@ describe 'Git LFS API and storage' do end context 'when downloading an lfs object that is assigned to other project' do - let(:other_project) { create(:empty_project) } + let(:other_project) { create(:project) } let(:update_lfs_permissions) do other_project.lfs_objects << lfs_object end @@ -559,7 +559,7 @@ describe 'Git LFS API and storage' do end context 'for other project' do - let(:other_project) { create(:empty_project) } + let(:other_project) { create(:project) } let(:pipeline) { create(:ci_empty_pipeline, project: other_project) } it 'rejects downloading code' do @@ -662,7 +662,7 @@ describe 'Git LFS API and storage' do end context 'when pushing an lfs object that already exists' do - let(:other_project) { create(:empty_project) } + let(:other_project) { create(:project) } let(:update_lfs_permissions) do other_project.lfs_objects << lfs_object end @@ -701,7 +701,7 @@ describe 'Git LFS API and storage' do expect(json_response['objects']).to be_kind_of(Array) expect(json_response['objects'].first['oid']).to eq("91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897") expect(json_response['objects'].first['size']).to eq(1575078) - expect(json_response['objects'].first['actions']['upload']['href']).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}.git/gitlab-lfs/objects/91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897/1575078") + expect(json_response['objects'].first['actions']['upload']['href']).to eq("#{Gitlab.config.gitlab.url}/#{project.full_path}.git/gitlab-lfs/objects/91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897/1575078") expect(json_response['objects'].first['actions']['upload']['header']).to eq('Authorization' => authorization) end end @@ -765,7 +765,7 @@ describe 'Git LFS API and storage' do end context 'tries to push to other project' do - let(:other_project) { create(:empty_project) } + let(:other_project) { create(:project) } let(:pipeline) { create(:ci_empty_pipeline, project: other_project) } let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) } @@ -806,7 +806,7 @@ describe 'Git LFS API and storage' do end describe 'unsupported' do - let(:project) { create(:empty_project) } + let(:project) { create(:project) } let(:authorization) { authorize_user } let(:body) do { @@ -894,7 +894,7 @@ describe 'Git LFS API and storage' do end describe 'to one project' do - let(:project) { create(:empty_project) } + let(:project) { create(:project) } describe 'when user is authenticated' do let(:authorization) { authorize_user } @@ -986,7 +986,7 @@ describe 'Git LFS API and storage' do end context 'tries to push to other project' do - let(:other_project) { create(:empty_project) } + let(:other_project) { create(:project) } let(:pipeline) { create(:ci_empty_pipeline, project: other_project) } let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) } @@ -1086,7 +1086,7 @@ describe 'Git LFS API and storage' do end context 'tries to push to other project' do - let(:other_project) { create(:empty_project) } + let(:other_project) { create(:project) } let(:pipeline) { create(:ci_empty_pipeline, project: other_project) } let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) } @@ -1111,7 +1111,7 @@ describe 'Git LFS API and storage' do end describe 'and second project not related to fork or a source project' do - let(:second_project) { create(:empty_project) } + let(:second_project) { create(:project) } let(:authorization) { authorize_user } before do diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb index e78d2cfdb33..e5d9d3df5a8 100644 --- a/spec/requests/projects/cycle_analytics_events_spec.rb +++ b/spec/requests/projects/cycle_analytics_events_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe 'cycle analytics events', api: true do +describe 'cycle analytics events' do let(:user) { create(:user) } let(:project) { create(:project, :repository, public_builds: false) } let(:issue) { create(:issue, project: project, created_at: 2.days.ago) } diff --git a/spec/requests/request_profiler_spec.rb b/spec/requests/request_profiler_spec.rb index 51fbfecec4b..9afeb2983b0 100644 --- a/spec/requests/request_profiler_spec.rb +++ b/spec/requests/request_profiler_spec.rb @@ -15,7 +15,7 @@ describe 'Request Profiler' do it 'creates a profile of the request' do project = create(:project, namespace: user.namespace) time = Time.now - path = "/#{project.path_with_namespace}" + path = "/#{project.full_path}" Timecop.freeze(time) do get path, nil, 'X-Profile-Token' => Gitlab::RequestProfiler.profile_token |