diff options
Diffstat (limited to 'spec/controllers')
25 files changed, 741 insertions, 87 deletions
diff --git a/spec/controllers/admin/impersonations_controller_spec.rb b/spec/controllers/admin/impersonations_controller_spec.rb index 8be662974a0..8f1f0ba89ff 100644 --- a/spec/controllers/admin/impersonations_controller_spec.rb +++ b/spec/controllers/admin/impersonations_controller_spec.rb @@ -76,18 +76,32 @@ describe Admin::ImpersonationsController do end context "when the impersonator is not blocked" do - it "redirects to the impersonated user's page" do - expect(Gitlab::AppLogger).to receive(:info).with("User #{impersonator.username} has stopped impersonating #{user.username}").and_call_original + shared_examples_for "successfully stops impersonating" do + it "redirects to the impersonated user's page" do + expect(Gitlab::AppLogger).to receive(:info).with("User #{impersonator.username} has stopped impersonating #{user.username}").and_call_original - delete :destroy + delete :destroy + + expect(response).to redirect_to(admin_user_path(user)) + end + + it "signs us in as the impersonator" do + delete :destroy - expect(response).to redirect_to(admin_user_path(user)) + expect(warden.user).to eq(impersonator) + end end - it "signs us in as the impersonator" do - delete :destroy + # base case + it_behaves_like "successfully stops impersonating" + + context "and the user has a temporary oauth e-mail address" do + before do + allow(user).to receive(:temp_oauth_email?).and_return(true) + allow(controller).to receive(:current_user).and_return(user) + end - expect(warden.user).to eq(impersonator) + it_behaves_like "successfully stops impersonating" end end end diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 98e912f000c..81cbccd5436 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -1,8 +1,9 @@ require 'spec_helper' describe ApplicationController do + let(:user) { create(:user) } + describe '#check_password_expiration' do - let(:user) { create(:user) } let(:controller) { ApplicationController.new } it 'redirects if the user is over their password expiry' do @@ -39,8 +40,6 @@ describe ApplicationController do end end - let(:user) { create(:user) } - context "when the 'private_token' param is populated with the private token" do it "logs the user in" do get :index, private_token: user.private_token @@ -73,7 +72,6 @@ describe ApplicationController do end end - let(:user) { create(:user) } let(:personal_access_token) { create(:personal_access_token, user: user) } context "when the 'personal_access_token' param is populated with the personal access token" do @@ -100,4 +98,21 @@ describe ApplicationController do end end end + + describe '#route_not_found' do + let(:controller) { ApplicationController.new } + + it 'renders 404 if authenticated' do + allow(controller).to receive(:current_user).and_return(user) + expect(controller).to receive(:not_found) + controller.send(:route_not_found) + end + + it 'does redirect to login page if not authenticated' do + allow(controller).to receive(:current_user).and_return(nil) + expect(controller).to receive(:redirect_to) + expect(controller).to receive(:new_user_session_path) + controller.send(:route_not_found) + end + end end diff --git a/spec/controllers/autocomplete_controller_spec.rb b/spec/controllers/autocomplete_controller_spec.rb index a121cb2fc97..ea2fd90a9b0 100644 --- a/spec/controllers/autocomplete_controller_spec.rb +++ b/spec/controllers/autocomplete_controller_spec.rb @@ -4,14 +4,14 @@ describe AutocompleteController do let!(:project) { create(:project) } let!(:user) { create(:user) } - context 'users and members' do + context 'GET users' do let!(:user2) { create(:user) } let!(:non_member) { create(:user) } context 'project members' do before do sign_in(user) - project.team << [user, :master] + project.add_master(user) end describe 'GET #users with project ID' do @@ -69,7 +69,7 @@ describe AutocompleteController do before do sign_in(non_member) - project.team << [user, :master] + project.add_master(user) end let(:body) { JSON.parse(response.body) } @@ -103,7 +103,7 @@ describe AutocompleteController do describe 'GET #users with public project' do before do - public_project.team << [user, :guest] + public_project.add_guest(user) get(:users, project_id: public_project.id) end @@ -129,7 +129,7 @@ describe AutocompleteController do describe 'GET #users with inaccessible group' do before do - project.team << [user, :guest] + project.add_guest(user) get(:users, group_id: user.namespace.id) end @@ -144,6 +144,15 @@ describe AutocompleteController do it { expect(body).to be_kind_of(Array) } it { expect(body.size).to eq 0 } end + + describe 'GET #users with todo filter' do + it 'gives an array of users' do + get :users, todo_filter: true + + expect(response.status).to eq 200 + expect(body).to be_kind_of(Array) + end + end end context 'author of issuable included' do @@ -180,18 +189,18 @@ describe AutocompleteController do end end - context 'projects' do + context 'GET projects' do let(:authorized_project) { create(:project) } let(:authorized_search_project) { create(:project, name: 'rugged') } before do sign_in(user) - project.team << [user, :master] + project.add_master(user) end context 'authorized projects' do before do - authorized_project.team << [user, :master] + authorized_project.add_master(user) end describe 'GET #projects with project ID' do @@ -216,8 +225,8 @@ describe AutocompleteController do context 'authorized projects and search' do before do - authorized_project.team << [user, :master] - authorized_search_project.team << [user, :master] + authorized_project.add_master(user) + authorized_search_project.add_master(user) end describe 'GET #projects with project ID and search' do @@ -242,9 +251,9 @@ describe AutocompleteController do authorized_project2 = create(:project) authorized_project3 = create(:project) - authorized_project.team << [user, :master] - authorized_project2.team << [user, :master] - authorized_project3.team << [user, :master] + authorized_project.add_master(user) + authorized_project2.add_master(user) + authorized_project3.add_master(user) stub_const 'MoveToProjectFinder::PAGE_SIZE', 2 end @@ -268,9 +277,9 @@ describe AutocompleteController do authorized_project2 = create(:project) authorized_project3 = create(:project) - authorized_project.team << [user, :master] - authorized_project2.team << [user, :master] - authorized_project3.team << [user, :master] + authorized_project.add_master(user) + authorized_project2.add_master(user) + authorized_project3.add_master(user) end describe 'GET #projects with project ID and offset_id' do @@ -289,7 +298,7 @@ describe AutocompleteController do context 'authorized projects without admin_issue ability' do before(:each) do - authorized_project.team << [user, :guest] + authorized_project.add_guest(user) expect(user.can?(:admin_issue, authorized_project)).to eq(false) end diff --git a/spec/controllers/groups/group_members_controller_spec.rb b/spec/controllers/groups/group_members_controller_spec.rb index c7db84dd5f9..60db0192dfd 100644 --- a/spec/controllers/groups/group_members_controller_spec.rb +++ b/spec/controllers/groups/group_members_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe Groups::GroupMembersController do let(:user) { create(:user) } - let(:group) { create(:group, :public) } + let(:group) { create(:group, :public, :access_requestable) } describe 'GET index' do it 'renders index with 200 status code' do diff --git a/spec/controllers/groups/labels_controller_spec.rb b/spec/controllers/groups/labels_controller_spec.rb new file mode 100644 index 00000000000..899d8ebd12b --- /dev/null +++ b/spec/controllers/groups/labels_controller_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe Groups::LabelsController do + let(:group) { create(:group) } + let(:user) { create(:user) } + + before do + group.add_owner(user) + + sign_in(user) + end + + describe 'POST #toggle_subscription' do + it 'allows user to toggle subscription on group labels' do + label = create(:group_label, group: group) + + post :toggle_subscription, group_id: group.to_param, id: label.to_param + + expect(response).to have_http_status(200) + end + end +end diff --git a/spec/controllers/help_controller_spec.rb b/spec/controllers/help_controller_spec.rb index 33c75e7584f..d3489324a9c 100644 --- a/spec/controllers/help_controller_spec.rb +++ b/spec/controllers/help_controller_spec.rb @@ -7,6 +7,38 @@ describe HelpController do sign_in(user) end + describe 'GET #index' do + context 'with absolute url' do + it 'keeps the URL absolute' do + stub_readme("[API](/api/README.md)") + + get :index + + expect(assigns[:help_index]).to eq '[API](/api/README.md)' + end + end + + context 'with relative url' do + it 'prefixes it with /help/' do + stub_readme("[API](api/README.md)") + + get :index + + expect(assigns[:help_index]).to eq '[API](/help/api/README.md)' + end + end + + context 'when url is an external link' do + it 'does not change it' do + stub_readme("[external](https://some.external.link)") + + get :index + + expect(assigns[:help_index]).to eq '[external](https://some.external.link)' + end + end + end + describe 'GET #show' do context 'for Markdown formats' do context 'when requested file exists' do @@ -72,4 +104,8 @@ describe HelpController do end end end + + def stub_readme(content) + allow(File).to receive(:read).and_return(content) + end end diff --git a/spec/controllers/import/bitbucket_controller_spec.rb b/spec/controllers/import/bitbucket_controller_spec.rb index 1d3c9fbbe2f..ce7c0b334ee 100644 --- a/spec/controllers/import/bitbucket_controller_spec.rb +++ b/spec/controllers/import/bitbucket_controller_spec.rb @@ -6,11 +6,11 @@ describe Import::BitbucketController do let(:user) { create(:user) } let(:token) { "asdasd12345" } let(:secret) { "sekrettt" } - let(:access_params) { { bitbucket_access_token: token, bitbucket_access_token_secret: secret } } + let(:refresh_token) { SecureRandom.hex(15) } + let(:access_params) { { token: token, expires_at: nil, expires_in: nil, refresh_token: nil } } def assign_session_tokens - session[:bitbucket_access_token] = token - session[:bitbucket_access_token_secret] = secret + session[:bitbucket_token] = token end before do @@ -24,29 +24,36 @@ describe Import::BitbucketController do end it "updates access token" do - access_token = double(token: token, secret: secret) - allow_any_instance_of(Gitlab::BitbucketImport::Client). + expires_at = Time.now + 1.day + expires_in = 1.day + access_token = double(token: token, + secret: secret, + expires_at: expires_at, + expires_in: expires_in, + refresh_token: refresh_token) + allow_any_instance_of(OAuth2::Client). to receive(:get_token).and_return(access_token) stub_omniauth_provider('bitbucket') get :callback - expect(session[:bitbucket_access_token]).to eq(token) - expect(session[:bitbucket_access_token_secret]).to eq(secret) + expect(session[:bitbucket_token]).to eq(token) + expect(session[:bitbucket_refresh_token]).to eq(refresh_token) + expect(session[:bitbucket_expires_at]).to eq(expires_at) + expect(session[:bitbucket_expires_in]).to eq(expires_in) expect(controller).to redirect_to(status_import_bitbucket_url) end end describe "GET status" do before do - @repo = OpenStruct.new(slug: 'vim', owner: 'asd') + @repo = double(slug: 'vim', owner: 'asd', full_name: 'asd/vim', "valid?" => true) assign_session_tokens end it "assigns variables" do @project = create(:project, import_type: 'bitbucket', creator_id: user.id) - client = stub_client(projects: [@repo]) - allow(client).to receive(:incompatible_projects).and_return([]) + allow_any_instance_of(Bitbucket::Client).to receive(:repos).and_return([@repo]) get :status @@ -57,7 +64,7 @@ describe Import::BitbucketController do it "does not show already added project" do @project = create(:project, import_type: 'bitbucket', creator_id: user.id, import_source: 'asd/vim') - stub_client(projects: [@repo]) + allow_any_instance_of(Bitbucket::Client).to receive(:repos).and_return([@repo]) get :status @@ -70,19 +77,16 @@ describe Import::BitbucketController do let(:bitbucket_username) { user.username } let(:bitbucket_user) do - { user: { username: bitbucket_username } }.with_indifferent_access + double(username: bitbucket_username) end let(:bitbucket_repo) do - { slug: "vim", owner: bitbucket_username }.with_indifferent_access + double(slug: "vim", owner: bitbucket_username, name: 'vim') end before do - allow(Gitlab::BitbucketImport::KeyAdder). - to receive(:new).with(bitbucket_repo, user, access_params). - and_return(double(execute: true)) - - stub_client(user: bitbucket_user, project: bitbucket_repo) + allow_any_instance_of(Bitbucket::Client).to receive(:repo).and_return(bitbucket_repo) + allow_any_instance_of(Bitbucket::Client).to receive(:user).and_return(bitbucket_user) assign_session_tokens end @@ -90,7 +94,7 @@ describe Import::BitbucketController do context "when the Bitbucket user and GitLab user's usernames match" do it "takes the current user's namespace" do expect(Gitlab::BitbucketImport::ProjectCreator). - to receive(:new).with(bitbucket_repo, user.namespace, user, access_params). + to receive(:new).with(bitbucket_repo, bitbucket_repo.name, user.namespace, user, access_params). and_return(double(execute: true)) post :create, format: :js @@ -102,7 +106,7 @@ describe Import::BitbucketController do it "takes the current user's namespace" do expect(Gitlab::BitbucketImport::ProjectCreator). - to receive(:new).with(bitbucket_repo, user.namespace, user, access_params). + to receive(:new).with(bitbucket_repo, bitbucket_repo.name, user.namespace, user, access_params). and_return(double(execute: true)) post :create, format: :js @@ -114,7 +118,7 @@ describe Import::BitbucketController do let(:other_username) { "someone_else" } before do - bitbucket_repo["owner"] = other_username + allow(bitbucket_repo).to receive(:owner).and_return(other_username) end context "when a namespace with the Bitbucket user's username already exists" do @@ -123,7 +127,7 @@ describe Import::BitbucketController do context "when the namespace is owned by the GitLab user" do it "takes the existing namespace" do expect(Gitlab::BitbucketImport::ProjectCreator). - to receive(:new).with(bitbucket_repo, existing_namespace, user, access_params). + to receive(:new).with(bitbucket_repo, bitbucket_repo.name, existing_namespace, user, access_params). and_return(double(execute: true)) post :create, format: :js @@ -156,7 +160,7 @@ describe Import::BitbucketController do it "takes the new namespace" do expect(Gitlab::BitbucketImport::ProjectCreator). - to receive(:new).with(bitbucket_repo, an_instance_of(Group), user, access_params). + to receive(:new).with(bitbucket_repo, bitbucket_repo.name, an_instance_of(Group), user, access_params). and_return(double(execute: true)) post :create, format: :js @@ -177,7 +181,7 @@ describe Import::BitbucketController do it "takes the current user's namespace" do expect(Gitlab::BitbucketImport::ProjectCreator). - to receive(:new).with(bitbucket_repo, user.namespace, user, access_params). + to receive(:new).with(bitbucket_repo, bitbucket_repo.name, user.namespace, user, access_params). and_return(double(execute: true)) post :create, format: :js diff --git a/spec/controllers/profiles/personal_access_tokens_spec.rb b/spec/controllers/profiles/personal_access_tokens_spec.rb new file mode 100644 index 00000000000..45534a3a587 --- /dev/null +++ b/spec/controllers/profiles/personal_access_tokens_spec.rb @@ -0,0 +1,49 @@ +require 'spec_helper' + +describe Profiles::PersonalAccessTokensController do + let(:user) { create(:user) } + + describe '#create' do + def created_token + PersonalAccessToken.order(:created_at).last + end + + before { sign_in(user) } + + it "allows creation of a token" do + name = FFaker::Product.brand + + post :create, personal_access_token: { name: name } + + expect(created_token).not_to be_nil + expect(created_token.name).to eq(name) + expect(created_token.expires_at).to be_nil + expect(PersonalAccessToken.active).to include(created_token) + end + + it "allows creation of a token with an expiry date" do + expires_at = 5.days.from_now + + post :create, personal_access_token: { name: FFaker::Product.brand, expires_at: expires_at } + + expect(created_token).not_to be_nil + expect(created_token.expires_at.to_i).to eq(expires_at.to_i) + end + + context "scopes" do + it "allows creation of a token with scopes" do + post :create, personal_access_token: { name: FFaker::Product.brand, scopes: ['api', 'read_user'] } + + expect(created_token).not_to be_nil + expect(created_token.scopes).to eq(['api', 'read_user']) + end + + it "allows creation of a token with no scopes" do + post :create, personal_access_token: { name: FFaker::Product.brand, scopes: [] } + + expect(created_token).not_to be_nil + expect(created_token.scopes).to eq([]) + end + end + end +end diff --git a/spec/controllers/projects/blob_controller_spec.rb b/spec/controllers/projects/blob_controller_spec.rb index 52d13fb6f9e..3efef757ae2 100644 --- a/spec/controllers/projects/blob_controller_spec.rb +++ b/spec/controllers/projects/blob_controller_spec.rb @@ -36,4 +36,53 @@ describe Projects::BlobController do end end end + + describe 'PUT update' do + let(:default_params) do + { + namespace_id: project.namespace.to_param, + project_id: project.to_param, + id: 'master/CHANGELOG', + target_branch: 'master', + content: 'Added changes', + commit_message: 'Update CHANGELOG' + } + end + + def blob_after_edit_path + namespace_project_blob_path(project.namespace, project, 'master/CHANGELOG') + end + + it 'redirects to blob' do + put :update, default_params + + expect(response).to redirect_to(blob_after_edit_path) + end + + context '?from_merge_request_iid' do + let(:merge_request) { create(:merge_request, source_project: project, target_project: project) } + let(:mr_params) { default_params.merge(from_merge_request_iid: merge_request.iid) } + + it 'redirects to MR diff' do + put :update, mr_params + + after_edit_path = diffs_namespace_project_merge_request_path(project.namespace, project, merge_request) + file_anchor = "##{Digest::SHA1.hexdigest('CHANGELOG')}" + expect(response).to redirect_to(after_edit_path + file_anchor) + end + + context "when user doesn't have access" do + before do + other_project = create(:empty_project) + merge_request.update!(source_project: other_project, target_project: other_project) + end + + it "it redirect to blob" do + put :update, mr_params + + expect(response).to redirect_to(blob_after_edit_path) + end + end + end + end end diff --git a/spec/controllers/projects/boards/issues_controller_spec.rb b/spec/controllers/projects/boards/issues_controller_spec.rb index cbe0417a4a7..299d2c981d3 100644 --- a/spec/controllers/projects/boards/issues_controller_spec.rb +++ b/spec/controllers/projects/boards/issues_controller_spec.rb @@ -25,7 +25,7 @@ describe Projects::Boards::IssuesController do create(:labeled_issue, project: project, labels: [planning]) create(:labeled_issue, project: project, labels: [development], due_date: Date.tomorrow) create(:labeled_issue, project: project, labels: [development], assignee: johndoe) - issue.subscribe(johndoe) + issue.subscribe(johndoe, project) list_issues user: user, board: board, list: list2 diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb index 644de308c64..b88586b8678 100644 --- a/spec/controllers/projects/branches_controller_spec.rb +++ b/spec/controllers/projects/branches_controller_spec.rb @@ -1,13 +1,13 @@ require 'spec_helper' describe Projects::BranchesController do - let(:project) { create(:project) } - let(:user) { create(:user) } + let(:project) { create(:project) } + let(:user) { create(:user) } + let(:developer) { create(:user) } before do - sign_in(user) - project.team << [user, :master] + project.team << [user, :developer] allow(project).to receive(:branches).and_return(['master', 'foo/bar/baz']) allow(project).to receive(:tags).and_return(['v1.0.0', 'v2.0.0']) @@ -19,6 +19,8 @@ describe Projects::BranchesController do context "on creation of a new branch" do before do + sign_in(user) + post :create, namespace_id: project.namespace.to_param, project_id: project.to_param, @@ -68,6 +70,10 @@ describe Projects::BranchesController do let(:branch) { "1-feature-branch" } let!(:issue) { create(:issue, project: project) } + before do + sign_in(user) + end + it 'redirects' do post :create, namespace_id: project.namespace.to_param, @@ -88,12 +94,34 @@ describe Projects::BranchesController do branch_name: branch, issue_iid: issue.iid end + + context 'without issue feature access' do + before do + project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) + project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE) + project.team.truncate + end + + it "doesn't post a system note" do + expect(SystemNoteService).not_to receive(:new_issue_branch) + + post :create, + namespace_id: project.namespace.to_param, + project_id: project.to_param, + branch_name: branch, + issue_iid: issue.iid + end + end end end describe "POST destroy with HTML format" do render_views + before do + sign_in(user) + end + it 'returns 303' do post :destroy, format: :html, @@ -109,6 +137,8 @@ describe Projects::BranchesController do render_views before do + sign_in(user) + post :destroy, format: :js, id: branch, @@ -139,4 +169,42 @@ describe Projects::BranchesController do it { expect(response).to have_http_status(404) } end end + + describe "DELETE destroy_all_merged" do + def destroy_all_merged + delete :destroy_all_merged, + namespace_id: project.namespace.to_param, + project_id: project.to_param + end + + context 'when user is allowed to push' do + before do + sign_in(user) + end + + it 'redirects to branches' do + destroy_all_merged + + expect(response).to redirect_to namespace_project_branches_path(project.namespace, project) + end + + it 'starts worker to delete merged branches' do + expect_any_instance_of(DeleteMergedBranchesService).to receive(:async_execute) + + destroy_all_merged + end + end + + context 'when user is not allowed to push' do + before do + sign_in(developer) + end + + it 'responds with status 404' do + destroy_all_merged + + expect(response).to have_http_status(404) + end + end + end end diff --git a/spec/controllers/projects/cycle_analytics_controller_spec.rb b/spec/controllers/projects/cycle_analytics_controller_spec.rb new file mode 100644 index 00000000000..a971adf0539 --- /dev/null +++ b/spec/controllers/projects/cycle_analytics_controller_spec.rb @@ -0,0 +1,43 @@ +require 'spec_helper' + +describe Projects::CycleAnalyticsController do + let(:project) { create(:project) } + let(:user) { create(:user) } + + before do + sign_in(user) + project.team << [user, :master] + end + + describe 'cycle analytics not set up flag' do + context 'with no data' do + it 'is true' do + get(:show, + namespace_id: project.namespace.to_param, + project_id: project.to_param) + + expect(response).to be_success + expect(assigns(:cycle_analytics_no_data)).to eq(true) + end + end + + context 'with data' do + before do + issue = create(:issue, project: project, created_at: 4.days.ago) + milestone = create(:milestone, project: project, created_at: 5.days.ago) + issue.update(milestone: milestone) + + create_merge_request_closing_issue(issue) + end + + it 'is false' do + get(:show, + namespace_id: project.namespace.to_param, + project_id: project.to_param) + + expect(response).to be_success + expect(assigns(:cycle_analytics_no_data)).to eq(false) + end + end + end +end diff --git a/spec/controllers/projects/environments_controller_spec.rb b/spec/controllers/projects/environments_controller_spec.rb index 768105cae95..bc5e2711125 100644 --- a/spec/controllers/projects/environments_controller_spec.rb +++ b/spec/controllers/projects/environments_controller_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe Projects::EnvironmentsController do + include ApiHelpers + let(:environment) { create(:environment) } let(:project) { environment.project } let(:user) { create(:user) } @@ -11,6 +13,27 @@ describe Projects::EnvironmentsController do sign_in(user) end + describe 'GET index' do + context 'when standardrequest has been made' do + it 'responds with status code 200' do + get :index, environment_params + + expect(response).to be_ok + end + end + + context 'when requesting JSON response' do + it 'responds with correct JSON' do + get :index, environment_params(format: :json) + + first_environment = json_response.first + + expect(first_environment).not_to be_empty + expect(first_environment['name']). to eq environment.name + end + end + end + describe 'GET show' do context 'with valid id' do it 'responds with a status code 200' do @@ -48,11 +71,9 @@ describe Projects::EnvironmentsController do end end - def environment_params - { - namespace_id: project.namespace, - project_id: project, - id: environment.id - } + def environment_params(opts = {}) + opts.reverse_merge(namespace_id: project.namespace, + project_id: project, + id: environment.id) end end diff --git a/spec/controllers/projects/forks_controller_spec.rb b/spec/controllers/projects/forks_controller_spec.rb index ac3469cb8a9..028ea067a97 100644 --- a/spec/controllers/projects/forks_controller_spec.rb +++ b/spec/controllers/projects/forks_controller_spec.rb @@ -67,4 +67,62 @@ describe Projects::ForksController do end end end + + describe 'GET new' do + def get_new + get :new, + namespace_id: project.namespace.to_param, + project_id: project.to_param + end + + context 'when user is signed in' do + it 'responds with status 200' do + sign_in(user) + + get_new + + expect(response).to have_http_status(200) + end + end + + context 'when user is not signed in' do + it 'redirects to the sign-in page' do + sign_out(user) + + get_new + + expect(response).to redirect_to(new_user_session_path) + end + end + end + + describe 'POST create' do + def post_create + post :create, + namespace_id: project.namespace.to_param, + project_id: project.to_param, + namespace_key: user.namespace.id + end + + context 'when user is signed in' do + it 'responds with status 302' do + sign_in(user) + + post_create + + expect(response).to have_http_status(302) + expect(response).to redirect_to(namespace_project_import_path(user.namespace, project)) + end + end + + context 'when user is not signed in' do + it 'redirects to the sign-in page' do + sign_out(user) + + post_create + + expect(response).to redirect_to(new_user_session_path) + end + end + end end diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb index 90419368f22..dbe5ddccbcf 100644 --- a/spec/controllers/projects/issues_controller_spec.rb +++ b/spec/controllers/projects/issues_controller_spec.rb @@ -55,6 +55,30 @@ describe Projects::IssuesController do end describe 'GET #new' do + context 'internal issue tracker' do + before do + sign_in(user) + project.team << [user, :developer] + end + + it 'builds a new issue' do + get :new, namespace_id: project.namespace.path, project_id: project + + expect(assigns(:issue)).to be_a_new(Issue) + end + + it 'fills in an issue for a merge request' do + project_with_repository = create(:project) + project_with_repository.team << [user, :developer] + mr = create(:merge_request_with_diff_notes, source_project: project_with_repository) + + get :new, namespace_id: project_with_repository.namespace.path, project_id: project_with_repository, merge_request_for_resolving_discussions: mr.iid + + expect(assigns(:issue).title).not_to be_empty + expect(assigns(:issue).description).not_to be_empty + end + end + context 'external issue tracker' do it 'redirects to the external issue tracker' do external = double(new_issue_path: 'https://example.com/issues/new') @@ -272,6 +296,42 @@ describe Projects::IssuesController do end describe 'POST #create' do + context 'resolving discussions in MergeRequest' do + let(:discussion) { Discussion.for_diff_notes([create(:diff_note_on_merge_request)]).first } + let(:merge_request) { discussion.noteable } + let(:project) { merge_request.source_project } + + before do + project.team << [user, :master] + sign_in user + end + + let(:merge_request_params) do + { merge_request_for_resolving_discussions: merge_request.iid } + end + + def post_issue(issue_params) + post :create, namespace_id: project.namespace.to_param, project_id: project.to_param, issue: issue_params, merge_request_for_resolving_discussions: merge_request.iid + end + + it 'creates an issue for the project' do + expect { post_issue({ title: 'Hello' }) }.to change { project.issues.reload.size }.by(1) + end + + it "doesn't overwrite given params" do + post_issue(description: 'Manually entered description') + + expect(assigns(:issue).description).to eq('Manually entered description') + end + + it 'resolves the discussion in the merge_request' do + post_issue(title: 'Hello') + discussion.first_note.reload + + expect(discussion.resolved?).to eq(true) + end + end + context 'Akismet is enabled' do before do allow_any_instance_of(SpamService).to receive(:check_for_spam?).and_return(true) diff --git a/spec/controllers/projects/labels_controller_spec.rb b/spec/controllers/projects/labels_controller_spec.rb index 8faecec0063..ec6cea5c0f4 100644 --- a/spec/controllers/projects/labels_controller_spec.rb +++ b/spec/controllers/projects/labels_controller_spec.rb @@ -72,14 +72,8 @@ describe Projects::LabelsController do end describe 'POST #generate' do - let(:admin) { create(:admin) } - - before do - sign_in(admin) - end - context 'personal project' do - let(:personal_project) { create(:empty_project) } + let(:personal_project) { create(:empty_project, namespace: user.namespace) } it 'creates labels' do post :generate, namespace_id: personal_project.namespace.to_param, project_id: personal_project.to_param @@ -96,4 +90,26 @@ describe Projects::LabelsController do end end end + + describe 'POST #toggle_subscription' do + it 'allows user to toggle subscription on project labels' do + label = create(:label, project: project) + + toggle_subscription(label) + + expect(response).to have_http_status(200) + end + + it 'allows user to toggle subscription on group labels' do + group_label = create(:group_label, group: group) + + toggle_subscription(group_label) + + expect(response).to have_http_status(200) + end + + def toggle_subscription(label) + post :toggle_subscription, namespace_id: project.namespace.to_param, project_id: project.to_param, id: label.to_param + end + end end diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 49127aecc63..9e0b80205d8 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -39,6 +39,17 @@ describe Projects::MergeRequestsController do end end + shared_examples "loads labels" do |action| + it "loads labels into the @labels variable" do + get action, + namespace_id: project.namespace.to_param, + project_id: project.to_param, + id: merge_request.iid, + format: 'html' + expect(assigns(:labels)).not_to be_nil + end + end + describe "GET show" do shared_examples "export merge as" do |format| it "does generally work" do @@ -51,6 +62,8 @@ describe Projects::MergeRequestsController do expect(response).to be_success end + it_behaves_like "loads labels", :show + it "generates it" do expect_any_instance_of(MergeRequest).to receive(:"to_#{format}") @@ -279,7 +292,9 @@ describe Projects::MergeRequestsController do it 'sets the MR to merge when the build succeeds' do service = double(:merge_when_build_succeeds_service) - expect(MergeRequests::MergeWhenBuildSucceedsService).to receive(:new).with(project, anything, anything).and_return(service) + expect(MergeRequests::MergeWhenPipelineSucceedsService) + .to receive(:new).with(project, anything, anything) + .and_return(service) expect(service).to receive(:execute).with(merge_request) merge_when_build_succeeds @@ -406,6 +421,8 @@ describe Projects::MergeRequestsController do get :diffs, params.merge(extra_params) end + it_behaves_like "loads labels", :diffs + context 'with default params' do context 'as html' do before { go(format: 'html') } @@ -612,6 +629,8 @@ describe Projects::MergeRequestsController do format: format end + it_behaves_like "loads labels", :commits + context 'as html' do it 'renders the show template' do go @@ -630,6 +649,14 @@ describe Projects::MergeRequestsController do end end + describe 'GET builds' do + it_behaves_like "loads labels", :builds + end + + describe 'GET pipelines' do + it_behaves_like "loads labels", :pipelines + end + describe 'GET conflicts' do let(:json_response) { JSON.parse(response.body) } diff --git a/spec/controllers/projects/milestones_controller_spec.rb b/spec/controllers/projects/milestones_controller_spec.rb index 7c5f33c63b8..6d30d085056 100644 --- a/spec/controllers/projects/milestones_controller_spec.rb +++ b/spec/controllers/projects/milestones_controller_spec.rb @@ -31,7 +31,7 @@ describe Projects::MilestonesController do # Check system note left for milestone removal last_note = project.issues.find(issue.id).notes[-1].note - expect(last_note).to eq('Milestone removed') + expect(last_note).to eq('removed milestone') end end end diff --git a/spec/controllers/projects/project_members_controller_spec.rb b/spec/controllers/projects/project_members_controller_spec.rb index 2a7523c6512..b52137fbe7e 100644 --- a/spec/controllers/projects/project_members_controller_spec.rb +++ b/spec/controllers/projects/project_members_controller_spec.rb @@ -2,7 +2,7 @@ require('spec_helper') describe Projects::ProjectMembersController do let(:user) { create(:user) } - let(:project) { create(:project, :public) } + let(:project) { create(:empty_project, :public, :access_requestable) } describe 'GET index' do it 'renders index with 200 status code' do diff --git a/spec/controllers/projects/releases_controller_spec.rb b/spec/controllers/projects/releases_controller_spec.rb new file mode 100644 index 00000000000..9fd5c3b85f6 --- /dev/null +++ b/spec/controllers/projects/releases_controller_spec.rb @@ -0,0 +1,55 @@ +require 'spec_helper' + +describe Projects::ReleasesController do + let!(:project) { create(:project) } + let!(:user) { create(:user) } + let!(:release) { create(:release, project: project) } + let!(:tag) { release.tag } + + before do + project.team << [user, :developer] + sign_in(user) + end + + describe 'GET #edit' do + it 'initializes a new release' do + tag_id = release.tag + project.releases.destroy_all + + get :edit, namespace_id: project.namespace.path, project_id: project.path, tag_id: tag_id + + release = assigns(:release) + expect(release).not_to be_nil + expect(release).not_to be_persisted + end + + it 'retrieves an existing release' do + get :edit, namespace_id: project.namespace.path, project_id: project.path, tag_id: release.tag + + release = assigns(:release) + expect(release).not_to be_nil + expect(release).to be_persisted + end + end + + describe 'PUT #update' do + it 'updates release note description' do + update_release('description updated') + + release = project.releases.find_by_tag(tag) + expect(release.description).to eq("description updated") + end + + it 'deletes release note when description is null' do + expect { update_release('') }.to change(project.releases, :count).by(-1) + end + end + + def update_release(description) + put :update, + namespace_id: project.namespace.to_param, + project_id: project.to_param, + tag_id: release.tag, + release: { description: description } + end +end diff --git a/spec/controllers/projects/todo_controller_spec.rb b/spec/controllers/projects/todo_controller_spec.rb index 936320a3709..415c264e0dd 100644 --- a/spec/controllers/projects/todo_controller_spec.rb +++ b/spec/controllers/projects/todo_controller_spec.rb @@ -4,7 +4,7 @@ describe Projects::TodosController do include ApiHelpers let(:user) { create(:user) } - let(:project) { create(:project) } + let(:project) { create(:empty_project) } let(:issue) { create(:issue, project: project) } let(:merge_request) { create(:merge_request, source_project: project) } @@ -42,7 +42,7 @@ describe Projects::TodosController do end end - context 'when not authorized' do + context 'when not authorized for project' do it 'does not create todo for issue that user has no access to' do sign_in(user) expect do @@ -60,6 +60,19 @@ describe Projects::TodosController do expect(response).to have_http_status(302) end end + + context 'when not authorized for issue' do + before do + project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) + project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE) + sign_in(user) + end + + it "doesn't create todo" do + expect{ go }.not_to change { user.todos.count } + expect(response).to have_http_status(404) + end + end end end @@ -97,7 +110,7 @@ describe Projects::TodosController do end end - context 'when not authorized' do + context 'when not authorized for project' do it 'does not create todo for merge request user has no access to' do sign_in(user) expect do @@ -115,6 +128,19 @@ describe Projects::TodosController do expect(response).to have_http_status(302) end end + + context 'when not authorized for merge_request' do + before do + project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) + project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE) + sign_in(user) + end + + it "doesn't create todo" do + expect{ go }.not_to change { user.todos.count } + expect(response).to have_http_status(404) + end + end end end end diff --git a/spec/controllers/search_controller_spec.rb b/spec/controllers/search_controller_spec.rb new file mode 100644 index 00000000000..b7bb9290712 --- /dev/null +++ b/spec/controllers/search_controller_spec.rb @@ -0,0 +1,61 @@ +require 'spec_helper' + +describe SearchController do + let(:user) { create(:user) } + let(:project) { create(:empty_project, :public) } + + before do + sign_in(user) + end + + it 'finds issue comments' do + project = create(:empty_project, :public) + note = create(:note_on_issue, project: project) + + get :show, project_id: project.id, scope: 'notes', search: note.note + + expect(assigns[:search_objects].first).to eq note + end + + context 'on restricted projects' do + context 'when signed out' do + before { sign_out(user) } + + it "doesn't expose comments on issues" do + project = create(:empty_project, :public, issues_access_level: ProjectFeature::PRIVATE) + note = create(:note_on_issue, project: project) + + get :show, project_id: project.id, scope: 'notes', search: note.note + + expect(assigns[:search_objects].count).to eq(0) + end + end + + it "doesn't expose comments on issues" do + project = create(:empty_project, :public, issues_access_level: ProjectFeature::PRIVATE) + note = create(:note_on_issue, project: project) + + get :show, project_id: project.id, scope: 'notes', search: note.note + + expect(assigns[:search_objects].count).to eq(0) + end + + it "doesn't expose comments on merge_requests" do + project = create(:empty_project, :public, merge_requests_access_level: ProjectFeature::PRIVATE) + note = create(:note_on_merge_request, project: project) + + get :show, project_id: project.id, scope: 'notes', search: note.note + + expect(assigns[:search_objects].count).to eq(0) + end + + it "doesn't expose comments on snippets" do + project = create(:empty_project, :public, snippets_access_level: ProjectFeature::PRIVATE) + note = create(:note_on_project_snippet, project: project) + + get :show, project_id: project.id, scope: 'notes', search: note.note + + expect(assigns[:search_objects].count).to eq(0) + end + end +end diff --git a/spec/controllers/sent_notifications_controller_spec.rb b/spec/controllers/sent_notifications_controller_spec.rb index 191e290a118..954fc2eaf21 100644 --- a/spec/controllers/sent_notifications_controller_spec.rb +++ b/spec/controllers/sent_notifications_controller_spec.rb @@ -3,11 +3,11 @@ require 'rails_helper' describe SentNotificationsController, type: :controller do let(:user) { create(:user) } let(:project) { create(:empty_project) } - let(:sent_notification) { create(:sent_notification, noteable: issue, recipient: user) } + let(:sent_notification) { create(:sent_notification, project: project, noteable: issue, recipient: user) } let(:issue) do create(:issue, project: project, author: user) do |issue| - issue.subscriptions.create(user: user, subscribed: true) + issue.subscriptions.create(user: user, project: project, subscribed: true) end end @@ -17,7 +17,7 @@ describe SentNotificationsController, type: :controller do before { get(:unsubscribe, id: sent_notification.reply_key, force: true) } it 'unsubscribes the user' do - expect(issue.subscribed?(user)).to be_falsey + expect(issue.subscribed?(user, project)).to be_falsey end it 'sets the flash message' do @@ -33,7 +33,7 @@ describe SentNotificationsController, type: :controller do before { get(:unsubscribe, id: sent_notification.reply_key) } it 'does not unsubscribe the user' do - expect(issue.subscribed?(user)).to be_truthy + expect(issue.subscribed?(user, project)).to be_truthy end it 'does not set the flash message' do @@ -53,7 +53,7 @@ describe SentNotificationsController, type: :controller do before { get(:unsubscribe, id: sent_notification.reply_key.reverse) } it 'does not unsubscribe the user' do - expect(issue.subscribed?(user)).to be_truthy + expect(issue.subscribed?(user, project)).to be_truthy end it 'does not set the flash message' do @@ -69,7 +69,7 @@ describe SentNotificationsController, type: :controller do before { get(:unsubscribe, id: sent_notification.reply_key, force: true) } it 'unsubscribes the user' do - expect(issue.subscribed?(user)).to be_falsey + expect(issue.subscribed?(user, project)).to be_falsey end it 'sets the flash message' do @@ -85,14 +85,14 @@ describe SentNotificationsController, type: :controller do context 'when the force param is not passed' do let(:merge_request) do create(:merge_request, source_project: project, author: user) do |merge_request| - merge_request.subscriptions.create(user: user, subscribed: true) + merge_request.subscriptions.create(user: user, project: project, subscribed: true) end end - let(:sent_notification) { create(:sent_notification, noteable: merge_request, recipient: user) } + let(:sent_notification) { create(:sent_notification, project: project, noteable: merge_request, recipient: user) } before { get(:unsubscribe, id: sent_notification.reply_key) } it 'unsubscribes the user' do - expect(merge_request.subscribed?(user)).to be_falsey + expect(merge_request.subscribed?(user, project)).to be_falsey end it 'sets the flash message' do diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb index 48d69377461..b56c7880b64 100644 --- a/spec/controllers/sessions_controller_spec.rb +++ b/spec/controllers/sessions_controller_spec.rb @@ -22,7 +22,6 @@ describe SessionsController do it 'authenticates user correctly' do post(:create, user: { login: user.username, password: user.password }) - expect(response).to set_flash.to /Signed in successfully/ expect(subject.current_user). to eq user end diff --git a/spec/controllers/snippets_controller_spec.rb b/spec/controllers/snippets_controller_spec.rb index 2d762fdaa04..d76fe9f580f 100644 --- a/spec/controllers/snippets_controller_spec.rb +++ b/spec/controllers/snippets_controller_spec.rb @@ -3,6 +3,28 @@ require 'spec_helper' describe SnippetsController do let(:user) { create(:user) } + describe 'GET #new' do + context 'when signed in' do + before do + sign_in(user) + end + + it 'responds with status 200' do + get :new + + expect(response).to have_http_status(200) + end + end + + context 'when not signed in' do + it 'redirects to the sign in page' do + get :new + + expect(response).to redirect_to(new_user_session_path) + end + end + end + describe 'GET #show' do context 'when the personal snippet is private' do let(:personal_snippet) { create(:personal_snippet, :private, author: user) } |