diff options
Diffstat (limited to 'spec/controllers')
28 files changed, 595 insertions, 78 deletions
diff --git a/spec/controllers/admin/projects_controller_spec.rb b/spec/controllers/admin/projects_controller_spec.rb index 2ba0d489197..4cb8b8da150 100644 --- a/spec/controllers/admin/projects_controller_spec.rb +++ b/spec/controllers/admin/projects_controller_spec.rb @@ -17,7 +17,7 @@ describe Admin::ProjectsController do it 'does not retrieve the project' do get :index, visibility_levels: [Gitlab::VisibilityLevel::INTERNAL] - expect(response.body).to_not match(project.name) + expect(response.body).not_to match(project.name) end end end diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb index ce2a62ae1fd..6caf37ddc2c 100644 --- a/spec/controllers/admin/users_controller_spec.rb +++ b/spec/controllers/admin/users_controller_spec.rb @@ -114,6 +114,82 @@ describe Admin::UsersController do end end + describe 'POST update' do + context 'when the password has changed' do + def update_password(user, password, password_confirmation = nil) + params = { + id: user.to_param, + user: { + password: password, + password_confirmation: password_confirmation || password + } + } + + post :update, params + end + + context 'when the new password is valid' do + it 'redirects to the user' do + update_password(user, 'AValidPassword1') + + expect(response).to redirect_to(admin_user_path(user)) + end + + it 'updates the password' do + update_password(user, 'AValidPassword1') + + expect { user.reload }.to change { user.encrypted_password } + end + + it 'sets the new password to expire immediately' do + update_password(user, 'AValidPassword1') + + expect { user.reload }.to change { user.password_expires_at }.to(a_value <= Time.now) + end + end + + context 'when the new password is invalid' do + it 'shows the edit page again' do + update_password(user, 'invalid') + + expect(response).to render_template(:edit) + end + + it 'returns the error message' do + update_password(user, 'invalid') + + expect(assigns[:user].errors).to contain_exactly(a_string_matching(/too short/)) + end + + it 'does not update the password' do + update_password(user, 'invalid') + + expect { user.reload }.not_to change { user.encrypted_password } + end + end + + context 'when the new password does not match the password confirmation' do + it 'shows the edit page again' do + update_password(user, 'AValidPassword1', 'AValidPassword2') + + expect(response).to render_template(:edit) + end + + it 'returns the error message' do + update_password(user, 'AValidPassword1', 'AValidPassword2') + + expect(assigns[:user].errors).to contain_exactly(a_string_matching(/doesn't match/)) + end + + it 'does not update the password' do + update_password(user, 'AValidPassword1', 'AValidPassword2') + + expect { user.reload }.not_to change { user.encrypted_password } + end + end + end + end + describe "POST impersonate" do context "when the user is blocked" do before do diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb index 465531b2b36..cd98fecd0c7 100644 --- a/spec/controllers/groups_controller_spec.rb +++ b/spec/controllers/groups_controller_spec.rb @@ -31,9 +31,9 @@ describe GroupsController do let(:issue_2) { create(:issue, project: project) } before do - create_list(:upvote_note, 3, project: project, noteable: issue_2) - create_list(:upvote_note, 2, project: project, noteable: issue_1) - create_list(:downvote_note, 2, project: project, noteable: issue_2) + create_list(:award_emoji, 3, awardable: issue_2) + create_list(:award_emoji, 2, awardable: issue_1) + create_list(:award_emoji, 2, :downvote, awardable: issue_2,) sign_in(user) end @@ -56,9 +56,9 @@ describe GroupsController do let(:merge_request_2) { create(:merge_request, :simple, source_project: project) } before do - create_list(:upvote_note, 3, project: project, noteable: merge_request_2) - create_list(:upvote_note, 2, project: project, noteable: merge_request_1) - create_list(:downvote_note, 2, project: project, noteable: merge_request_2) + create_list(:award_emoji, 3, awardable: merge_request_2) + create_list(:award_emoji, 2, awardable: merge_request_1) + create_list(:award_emoji, 2, :downvote, awardable: merge_request_2) sign_in(user) end diff --git a/spec/controllers/health_check_controller_spec.rb b/spec/controllers/health_check_controller_spec.rb new file mode 100644 index 00000000000..0d8a68bb51a --- /dev/null +++ b/spec/controllers/health_check_controller_spec.rb @@ -0,0 +1,105 @@ +require 'spec_helper' + +describe HealthCheckController do + let(:token) { current_application_settings.health_check_access_token } + let(:json_response) { JSON.parse(response.body) } + let(:xml_response) { Hash.from_xml(response.body)['hash'] } + + describe 'GET #index' do + context 'when services are up but NO access token' do + it 'returns a not found page' do + get :index + expect(response).to be_not_found + end + end + + context 'when services are up and an access token is provided' do + it 'supports passing the token in the header' do + request.headers['TOKEN'] = token + get :index + expect(response).to be_success + expect(response.content_type).to eq 'text/plain' + end + + it 'supports successful plaintest response' do + get :index, token: token + expect(response).to be_success + expect(response.content_type).to eq 'text/plain' + end + + it 'supports successful json response' do + get :index, token: token, format: :json + expect(response).to be_success + expect(response.content_type).to eq 'application/json' + expect(json_response['healthy']).to be true + end + + it 'supports successful xml response' do + get :index, token: token, format: :xml + expect(response).to be_success + expect(response.content_type).to eq 'application/xml' + expect(xml_response['healthy']).to be true + end + + it 'supports successful responses for specific checks' do + get :index, token: token, checks: 'email', format: :json + expect(response).to be_success + expect(response.content_type).to eq 'application/json' + expect(json_response['healthy']).to be true + end + end + + context 'when a service is down but NO access token' do + it 'returns a not found page' do + get :index + expect(response).to be_not_found + end + end + + context 'when a service is down and an access token is provided' do + before do + allow(HealthCheck::Utils).to receive(:process_checks).with('standard').and_return('The server is on fire') + allow(HealthCheck::Utils).to receive(:process_checks).with('email').and_return('Email is on fire') + end + + it 'supports passing the token in the header' do + request.headers['TOKEN'] = token + get :index + expect(response.status).to eq(500) + expect(response.content_type).to eq 'text/plain' + expect(response.body).to include('The server is on fire') + end + + it 'supports failure plaintest response' do + get :index, token: token + expect(response.status).to eq(500) + expect(response.content_type).to eq 'text/plain' + expect(response.body).to include('The server is on fire') + end + + it 'supports failure json response' do + get :index, token: token, format: :json + expect(response.status).to eq(500) + expect(response.content_type).to eq 'application/json' + expect(json_response['healthy']).to be false + expect(json_response['message']).to include('The server is on fire') + end + + it 'supports failure xml response' do + get :index, token: token, format: :xml + expect(response.status).to eq(500) + expect(response.content_type).to eq 'application/xml' + expect(xml_response['healthy']).to be false + expect(xml_response['message']).to include('The server is on fire') + end + + it 'supports failure responses for specific checks' do + get :index, token: token, checks: 'email', format: :json + expect(response.status).to eq(500) + expect(response.content_type).to eq 'application/json' + expect(json_response['healthy']).to be false + expect(json_response['message']).to include('Email is on fire') + end + end + end +end diff --git a/spec/controllers/import/bitbucket_controller_spec.rb b/spec/controllers/import/bitbucket_controller_spec.rb index 81c03c9059b..07bf8d2d1c3 100644 --- a/spec/controllers/import/bitbucket_controller_spec.rb +++ b/spec/controllers/import/bitbucket_controller_spec.rb @@ -1,5 +1,4 @@ require 'spec_helper' -require_relative 'import_spec_helper' describe Import::BitbucketController do include ImportSpecHelper diff --git a/spec/controllers/import/fogbugz_controller_spec.rb b/spec/controllers/import/fogbugz_controller_spec.rb index 27b11267d2a..5f0f6dea821 100644 --- a/spec/controllers/import/fogbugz_controller_spec.rb +++ b/spec/controllers/import/fogbugz_controller_spec.rb @@ -1,5 +1,4 @@ require 'spec_helper' -require_relative 'import_spec_helper' describe Import::FogbugzController do include ImportSpecHelper diff --git a/spec/controllers/import/github_controller_spec.rb b/spec/controllers/import/github_controller_spec.rb index bcc713dce2a..c55a3c28208 100644 --- a/spec/controllers/import/github_controller_spec.rb +++ b/spec/controllers/import/github_controller_spec.rb @@ -1,5 +1,4 @@ require 'spec_helper' -require_relative 'import_spec_helper' describe Import::GithubController do include ImportSpecHelper diff --git a/spec/controllers/import/gitlab_controller_spec.rb b/spec/controllers/import/gitlab_controller_spec.rb index 198d006af76..e8cf6aa7767 100644 --- a/spec/controllers/import/gitlab_controller_spec.rb +++ b/spec/controllers/import/gitlab_controller_spec.rb @@ -1,5 +1,4 @@ require 'spec_helper' -require_relative 'import_spec_helper' describe Import::GitlabController do include ImportSpecHelper diff --git a/spec/controllers/import/gitorious_controller_spec.rb b/spec/controllers/import/gitorious_controller_spec.rb index 7cb1b85a46d..4ae2b78e11c 100644 --- a/spec/controllers/import/gitorious_controller_spec.rb +++ b/spec/controllers/import/gitorious_controller_spec.rb @@ -1,5 +1,4 @@ require 'spec_helper' -require_relative 'import_spec_helper' describe Import::GitoriousController do include ImportSpecHelper diff --git a/spec/controllers/import/google_code_controller_spec.rb b/spec/controllers/import/google_code_controller_spec.rb index 66088139a69..4241db6e771 100644 --- a/spec/controllers/import/google_code_controller_spec.rb +++ b/spec/controllers/import/google_code_controller_spec.rb @@ -1,5 +1,4 @@ require 'spec_helper' -require_relative 'import_spec_helper' describe Import::GoogleCodeController do include ImportSpecHelper diff --git a/spec/controllers/import/import_spec_helper.rb b/spec/controllers/import/import_spec_helper.rb deleted file mode 100644 index 9d7648e25a7..00000000000 --- a/spec/controllers/import/import_spec_helper.rb +++ /dev/null @@ -1,33 +0,0 @@ -require 'ostruct' - -# Helper methods for controller specs in the Import namespace -# -# Must be included manually. -module ImportSpecHelper - # Stub `controller` to return a null object double with the provided messages - # when `client` is called - # - # Examples: - # - # stub_client(foo: %w(foo)) - # - # controller.client.foo # => ["foo"] - # controller.client.bar.baz.foo # => ["foo"] - # - # Returns the client double - def stub_client(messages = {}) - client = double('client', messages).as_null_object - allow(controller).to receive(:client).and_return(client) - - client - end - - def stub_omniauth_provider(name) - provider = OpenStruct.new( - name: name, - app_id: 'asd123', - app_secret: 'asd123' - ) - Gitlab.config.omniauth.providers << provider - end -end diff --git a/spec/controllers/oauth/applications_controller_spec.rb b/spec/controllers/oauth/applications_controller_spec.rb new file mode 100644 index 00000000000..af378304893 --- /dev/null +++ b/spec/controllers/oauth/applications_controller_spec.rb @@ -0,0 +1,29 @@ +require 'spec_helper' + +describe Oauth::ApplicationsController do + let(:user) { create(:user) } + + context 'project members' do + before do + sign_in(user) + end + + describe 'GET #index' do + it 'shows list of applications' do + get :index + + expect(response.status).to eq(200) + end + + it 'redirects back to profile page if OAuth applications are disabled' do + settings = double(user_oauth_applications?: false) + allow_any_instance_of(Gitlab::CurrentSettings).to receive(:current_application_settings).and_return(settings) + + get :index + + expect(response.status).to eq(302) + expect(response).to redirect_to(profile_path) + end + end + end +end diff --git a/spec/controllers/profiles/two_factor_auths_controller_spec.rb b/spec/controllers/profiles/two_factor_auths_controller_spec.rb index 4fb1473c2d2..d08d0018b35 100644 --- a/spec/controllers/profiles/two_factor_auths_controller_spec.rb +++ b/spec/controllers/profiles/two_factor_auths_controller_spec.rb @@ -8,21 +8,21 @@ describe Profiles::TwoFactorAuthsController do allow(subject).to receive(:current_user).and_return(user) end - describe 'GET new' do + describe 'GET show' do let(:user) { create(:user) } it 'generates otp_secret for user' do expect(User).to receive(:generate_otp_secret).with(32).and_return('secret').once - get :new - get :new # Second hit shouldn't re-generate it + get :show + get :show # Second hit shouldn't re-generate it end it 'assigns qr_code' do code = double('qr code') expect(subject).to receive(:build_qr_code).and_return(code) - get :new + get :show expect(assigns[:qr_code]).to eq code end end @@ -40,7 +40,7 @@ describe Profiles::TwoFactorAuthsController do expect(user).to receive(:validate_and_consume_otp!).with(pin).and_return(true) end - it 'sets two_factor_enabled' do + it 'enables 2fa for the user' do go user.reload @@ -79,9 +79,9 @@ describe Profiles::TwoFactorAuthsController do expect(assigns[:qr_code]).to eq code end - it 'renders new' do + it 'renders show' do go - expect(response).to render_template(:new) + expect(response).to render_template(:show) end end end diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb index 8ad73472117..c4b4a888b4e 100644 --- a/spec/controllers/projects/branches_controller_spec.rb +++ b/spec/controllers/projects/branches_controller_spec.rb @@ -122,27 +122,23 @@ describe Projects::BranchesController do let(:branch) { "feature" } it { expect(response.status).to eq(200) } - it { expect(subject).to render_template('destroy') } end context "valid branch name with unencoded slashes" do let(:branch) { "improve/awesome" } it { expect(response.status).to eq(200) } - it { expect(subject).to render_template('destroy') } end context "valid branch name with encoded slashes" do let(:branch) { "improve%2Fawesome" } it { expect(response.status).to eq(200) } - it { expect(subject).to render_template('destroy') } end context "invalid branch name, valid ref" do let(:branch) { "no-branch" } it { expect(response.status).to eq(404) } - it { expect(subject).to render_template('destroy') } end end end diff --git a/spec/controllers/projects/compare_controller_spec.rb b/spec/controllers/projects/compare_controller_spec.rb index 788a609ee40..4018dac95a2 100644 --- a/spec/controllers/projects/compare_controller_spec.rb +++ b/spec/controllers/projects/compare_controller_spec.rb @@ -19,7 +19,7 @@ describe Projects::CompareController do to: ref_to) expect(response).to be_success - expect(assigns(:diffs).first).to_not be_nil + expect(assigns(:diffs).first).not_to be_nil expect(assigns(:commits).length).to be >= 1 end @@ -32,7 +32,7 @@ describe Projects::CompareController do w: 1) expect(response).to be_success - expect(assigns(:diffs).first).to_not be_nil + expect(assigns(:diffs).first).not_to be_nil expect(assigns(:commits).length).to be >= 1 # without whitespace option, there are more than 2 diff_splits diff_splits = assigns(:diffs).first.diff.split("\n") diff --git a/spec/controllers/projects/group_links_controller_spec.rb b/spec/controllers/projects/group_links_controller_spec.rb index 40bd83af861..fbe8758dda7 100644 --- a/spec/controllers/projects/group_links_controller_spec.rb +++ b/spec/controllers/projects/group_links_controller_spec.rb @@ -28,7 +28,7 @@ describe Projects::GroupLinksController do expect(group.shared_projects).to include project end - it 'redirects to project group links page'do + it 'redirects to project group links page' do expect(response).to redirect_to( namespace_project_group_links_path(project.namespace, project) ) @@ -43,7 +43,7 @@ describe Projects::GroupLinksController do end it 'does not share project with that group' do - expect(group.shared_projects).to_not include project + expect(group.shared_projects).not_to include project end end end diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb index 2b2ad3b9412..78be7e3dc35 100644 --- a/spec/controllers/projects/issues_controller_spec.rb +++ b/spec/controllers/projects/issues_controller_spec.rb @@ -56,7 +56,7 @@ describe Projects::IssuesController do move_issue expect(response).to have_http_status :found - expect(another_project.issues).to_not be_empty + expect(another_project.issues).not_to be_empty end end @@ -250,4 +250,20 @@ describe Projects::IssuesController do end end end + + describe 'POST #toggle_award_emoji' do + before do + sign_in(user) + project.team << [user, :developer] + end + + it "toggles the award emoji" do + expect do + post(:toggle_award_emoji, namespace_id: project.namespace.path, + project_id: project.path, id: issue.iid, name: "thumbsup") + end.to change { issue.award_emoji.count }.by(1) + + expect(response.status).to eq(200) + end + end end diff --git a/spec/controllers/projects/labels_controller_spec.rb b/spec/controllers/projects/labels_controller_spec.rb new file mode 100644 index 00000000000..ab1dd34ed57 --- /dev/null +++ b/spec/controllers/projects/labels_controller_spec.rb @@ -0,0 +1,53 @@ +require 'spec_helper' + +describe Projects::LabelsController do + let(:project) { create(:project) } + let(:user) { create(:user) } + + before do + project.team << [user, :master] + sign_in(user) + end + + describe 'GET #index' do + def create_label(attributes) + create(:label, attributes.merge(project: project)) + end + + before do + 15.times { |i| create_label(priority: (i % 3) + 1, title: "label #{15 - i}") } + 5.times { |i| create_label(title: "label #{100 - i}") } + + + get :index, namespace_id: project.namespace.to_param, project_id: project.to_param + end + + context '@prioritized_labels' do + let(:prioritized_labels) { assigns(:prioritized_labels) } + + it 'contains only prioritized labels' do + expect(prioritized_labels).to all(have_attributes(priority: a_value > 0)) + end + + it 'is sorted by priority, then label title' do + priorities_and_titles = prioritized_labels.pluck(:priority, :title) + + expect(priorities_and_titles.sort).to eq(priorities_and_titles) + end + end + + context '@labels' do + let(:labels) { assigns(:labels) } + + it 'contains only unprioritized labels' do + expect(labels).to all(have_attributes(priority: nil)) + end + + it 'is sorted by label title' do + titles = labels.pluck(:title) + + expect(titles.sort).to eq(titles) + end + end + end +end diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index c0a1f45195f..4b408c03703 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -63,7 +63,7 @@ describe Projects::MergeRequestsController do id: merge_request.iid, format: format) - expect(response.body).to eq((merge_request.send(:"to_#{format}")).to_s) + expect(response.body).to eq(merge_request.send(:"to_#{format}").to_s) end it "should not escape Html" do @@ -84,17 +84,14 @@ describe Projects::MergeRequestsController do end describe "as diff" do - include_examples "export merge as", :diff - let(:format) { :diff } - - it "should really only be a git diff" do + it "triggers workhorse to serve the request" do get(:show, namespace_id: project.namespace.to_param, project_id: project.to_param, id: merge_request.iid, - format: format) + format: :diff) - expect(response.body).to start_with("diff --git") + expect(response.headers[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with("git-diff:") end end @@ -185,6 +182,92 @@ describe Projects::MergeRequestsController do end end + describe 'POST #merge' do + let(:base_params) do + { + namespace_id: project.namespace.path, + project_id: project.path, + id: merge_request.iid, + format: 'raw' + } + end + + context 'when the user does not have access' do + before do + project.team.truncate + project.team << [user, :reporter] + post :merge, base_params + end + + it 'returns not found' do + expect(response).to be_not_found + end + end + + context 'when the merge request is not mergeable' do + before do + merge_request.update_attributes(title: "WIP: #{merge_request.title}") + + post :merge, base_params + end + + it 'returns :failed' do + expect(assigns(:status)).to eq(:failed) + end + end + + context 'when the sha parameter does not match the source SHA' do + before { post :merge, base_params.merge(sha: 'foo') } + + it 'returns :sha_mismatch' do + expect(assigns(:status)).to eq(:sha_mismatch) + end + end + + context 'when the sha parameter matches the source SHA' do + def merge_with_sha + post :merge, base_params.merge(sha: merge_request.source_sha) + end + + it 'returns :success' do + merge_with_sha + + expect(assigns(:status)).to eq(:success) + end + + it 'starts the merge immediately' do + expect(MergeWorker).to receive(:perform_async).with(merge_request.id, anything, anything) + + merge_with_sha + end + + context 'when merge_when_build_succeeds is passed' do + def merge_when_build_succeeds + post :merge, base_params.merge(sha: merge_request.source_sha, merge_when_build_succeeds: '1') + end + + before do + create(:ci_empty_pipeline, project: project, sha: merge_request.source_sha, ref: merge_request.source_branch) + end + + it 'returns :merge_when_build_succeeds' do + merge_when_build_succeeds + + expect(assigns(:status)).to eq(:merge_when_build_succeeds) + end + + 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(service).to receive(:execute).with(merge_request) + + merge_when_build_succeeds + end + end + end + end + describe "DELETE #destroy" do it "denies access to users unless they're admin or project owner" do delete :destroy, namespace_id: project.namespace.path, project_id: project.path, id: merge_request.iid diff --git a/spec/controllers/projects/notes_controller_spec.rb b/spec/controllers/projects/notes_controller_spec.rb new file mode 100644 index 00000000000..00bc38b6071 --- /dev/null +++ b/spec/controllers/projects/notes_controller_spec.rb @@ -0,0 +1,36 @@ +require('spec_helper') + +describe Projects::NotesController do + let(:user) { create(:user) } + let(:project) { create(:project) } + let(:issue) { create(:issue, project: project) } + let(:note) { create(:note, noteable: issue, project: project) } + + describe 'POST #toggle_award_emoji' do + before do + sign_in(user) + project.team << [user, :developer] + end + + it "toggles the award emoji" do + expect do + post(:toggle_award_emoji, namespace_id: project.namespace.path, + project_id: project.path, id: note.id, name: "thumbsup") + end.to change { note.award_emoji.count }.by(1) + + expect(response.status).to eq(200) + end + + it "removes the already awarded emoji" do + post(:toggle_award_emoji, namespace_id: project.namespace.path, + project_id: project.path, id: note.id, name: "thumbsup") + + expect do + post(:toggle_award_emoji, namespace_id: project.namespace.path, + project_id: project.path, id: note.id, name: "thumbsup") + end.to change { AwardEmoji.count }.by(-1) + + expect(response.status).to eq(200) + end + end +end diff --git a/spec/controllers/projects/notification_settings_controller_spec.rb b/spec/controllers/projects/notification_settings_controller_spec.rb index 4908b545648..c5d17d97ec9 100644 --- a/spec/controllers/projects/notification_settings_controller_spec.rb +++ b/spec/controllers/projects/notification_settings_controller_spec.rb @@ -34,5 +34,19 @@ describe Projects::NotificationSettingsController do expect(response.status).to eq 200 end end + + context 'not authorized' do + let(:private_project) { create(:project, :private) } + before { sign_in(user) } + + it 'returns 404' do + put :update, + namespace_id: private_project.namespace.to_param, + project_id: private_project.to_param, + notification_setting: { level: :participating } + + expect(response.status).to eq(404) + end + end end end diff --git a/spec/controllers/projects/project_members_controller_spec.rb b/spec/controllers/projects/project_members_controller_spec.rb index ed64e7cf9af..750fbecdd07 100644 --- a/spec/controllers/projects/project_members_controller_spec.rb +++ b/spec/controllers/projects/project_members_controller_spec.rb @@ -38,7 +38,7 @@ describe Projects::ProjectMembersController do include_context 'import applied' it 'does not import team members' do - expect(project.team_members).to_not include member + expect(project.team_members).not_to include member end it 'responds with not found' do diff --git a/spec/controllers/projects/raw_controller_spec.rb b/spec/controllers/projects/raw_controller_spec.rb index 1caa476d37d..33c35161da3 100644 --- a/spec/controllers/projects/raw_controller_spec.rb +++ b/spec/controllers/projects/raw_controller_spec.rb @@ -17,6 +17,7 @@ describe Projects::RawController do expect(response.header['Content-Type']).to eq('text/plain; charset=utf-8') expect(response.header['Content-Disposition']). to eq("inline") + expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with("git-blob:") end end @@ -31,6 +32,7 @@ describe Projects::RawController do expect(response.status).to eq(200) expect(response.header['Content-Type']).to eq('image/jpeg') + expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with("git-blob:") end end @@ -42,7 +44,7 @@ describe Projects::RawController do before do public_project.lfs_objects << lfs_object allow_any_instance_of(LfsObjectUploader).to receive(:exists?).and_return(true) - allow(controller).to receive(:send_file) { controller.render nothing: true } + allow(controller).to receive(:send_file) { controller.head :ok } end it 'serves the file' do diff --git a/spec/controllers/projects/repositories_controller_spec.rb b/spec/controllers/projects/repositories_controller_spec.rb index 0ddbec9eac2..aad62cf20e3 100644 --- a/spec/controllers/projects/repositories_controller_spec.rb +++ b/spec/controllers/projects/repositories_controller_spec.rb @@ -20,10 +20,11 @@ describe Projects::RepositoriesController do project.team << [user, :developer] sign_in(user) end - it "uses Gitlab::Workhorse" do - expect(Gitlab::Workhorse).to receive(:send_git_archive).with(project, "master", "zip") + it "uses Gitlab::Workhorse" do get :archive, namespace_id: project.namespace.path, project_id: project.path, ref: "master", format: "zip" + + expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with("git-archive:") end context "when the service raises an error" do diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 069cd917e5a..fba545560c7 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -8,6 +8,40 @@ describe ProjectsController do let(:txt) { fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') } describe "GET show" do + context "user not project member" do + before { sign_in(user) } + + context "user does not have access to project" do + let(:private_project) { create(:project, :private) } + + it "does not initialize notification setting" do + get :show, namespace_id: private_project.namespace.path, id: private_project.path + expect(assigns(:notification_setting)).to be_nil + end + end + + context "user has access to project" do + context "and does not have notification setting" do + it "initializes notification as disabled" do + get :show, namespace_id: public_project.namespace.path, id: public_project.path + expect(assigns(:notification_setting).level).to eq("global") + end + end + + context "and has notification setting" do + before do + setting = user.notification_settings_for(public_project) + setting.level = :watch + setting.save + end + + it "shows current notification setting" do + get :show, namespace_id: public_project.namespace.path, id: public_project.path + expect(assigns(:notification_setting).level).to eq("watch") + end + end + end + end context "rendering default project view" do render_views @@ -81,6 +115,17 @@ describe ProjectsController do expect(public_project_with_dot_atom).not_to be_valid end end + + context 'when the project is pending deletions' do + it 'renders a 404 error' do + project = create(:project, pending_delete: true) + sign_in(user) + + get :show, namespace_id: project.namespace.path, id: project.path + + expect(response.status).to eq 404 + end + end end describe "#update" do diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb new file mode 100644 index 00000000000..209fa37d97d --- /dev/null +++ b/spec/controllers/registrations_controller_spec.rb @@ -0,0 +1,33 @@ +require 'spec_helper' + +describe RegistrationsController do + describe '#create' do + around(:each) do |example| + perform_enqueued_jobs do + example.run + end + end + + let(:user_params) { { user: { name: "new_user", username: "new_username", email: "new@user.com", password: "Any_password" } } } + + context 'when sending email confirmation' do + before { allow_any_instance_of(ApplicationSetting).to receive(:send_user_confirmation_email).and_return(false) } + + it 'logs user in directly' do + post(:create, user_params) + expect(ActionMailer::Base.deliveries.last).to be_nil + expect(subject.current_user).not_to be_nil + end + end + + context 'when not sending email confirmation' do + before { allow_any_instance_of(ApplicationSetting).to receive(:send_user_confirmation_email).and_return(true) } + + it 'does not authenticate user and sends confirmation email' do + post(:create, user_params) + expect(ActionMailer::Base.deliveries.last.to.first).to eq(user_params[:user][:email]) + expect(subject.current_user).to be_nil + end + end + end +end diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb index 83cc8ec6d26..4e9bfb0c69b 100644 --- a/spec/controllers/sessions_controller_spec.rb +++ b/spec/controllers/sessions_controller_spec.rb @@ -12,7 +12,7 @@ describe SessionsController do post(:create, user: { login: 'invalid', password: 'invalid' }) expect(response) - .to set_flash.now[:alert].to /Invalid login or password/ + .to set_flash.now[:alert].to /Invalid Login or password/ end end @@ -25,16 +25,42 @@ describe SessionsController do expect(response).to set_flash.to /Signed in successfully/ expect(subject.current_user). to eq user end + + it "creates an audit log record" do + expect { post(:create, user: { login: user.username, password: user.password }) }.to change { SecurityEvent.count }.by(1) + expect(SecurityEvent.last.details[:with]).to eq("standard") + end end end - context 'when using two-factor authentication' do + context 'when using two-factor authentication via OTP' do let(:user) { create(:user, :two_factor) } def authenticate_2fa(user_params) post(:create, { user: user_params }, { otp_user_id: user.id }) end + context 'remember_me field' do + it 'sets a remember_user_token cookie when enabled' do + allow(controller).to receive(:find_user).and_return(user) + expect(controller). + to receive(:remember_me).with(user).and_call_original + + authenticate_2fa(remember_me: '1', otp_attempt: user.current_otp) + + expect(response.cookies['remember_user_token']).to be_present + end + + it 'does nothing when disabled' do + allow(controller).to receive(:find_user).and_return(user) + expect(controller).not_to receive(:remember_me) + + authenticate_2fa(remember_me: '0', otp_attempt: user.current_otp) + + expect(response.cookies['remember_user_token']).to be_nil + end + end + ## # See #14900 issue # @@ -47,7 +73,7 @@ describe SessionsController do authenticate_2fa(login: another_user.username, otp_attempt: another_user.current_otp) - expect(subject.current_user).to_not eq another_user + expect(subject.current_user).not_to eq another_user end end @@ -56,7 +82,7 @@ describe SessionsController do authenticate_2fa(login: another_user.username, otp_attempt: 'invalid') - expect(subject.current_user).to_not eq another_user + expect(subject.current_user).not_to eq another_user end end @@ -73,7 +99,7 @@ describe SessionsController do before { authenticate_2fa(otp_attempt: 'invalid') } it 'does not authenticate' do - expect(subject.current_user).to_not eq user + expect(subject.current_user).not_to eq user end it 'warns about invalid OTP code' do @@ -96,6 +122,25 @@ describe SessionsController do end end end + + it "creates an audit log record" do + expect { authenticate_2fa(login: user.username, otp_attempt: user.current_otp) }.to change { SecurityEvent.count }.by(1) + expect(SecurityEvent.last.details[:with]).to eq("two-factor") + end + end + + context 'when using two-factor authentication via U2F device' do + let(:user) { create(:user, :two_factor) } + + def authenticate_2fa_u2f(user_params) + post(:create, { user: user_params }, { otp_user_id: user.id }) + end + + it "creates an audit log record" do + allow(U2fRegistration).to receive(:authenticate).and_return(true) + expect { authenticate_2fa_u2f(login: user.username, device_response: "{}") }.to change { SecurityEvent.count }.by(1) + expect(SecurityEvent.last.details[:with]).to eq("two-factor-via-u2f-device") + end end end end diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 8045c8b940d..c61ec174665 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -112,4 +112,26 @@ describe UsersController do expect(response).to render_template('calendar_activities') end end + + describe 'GET #snippets' do + before do + sign_in(user) + end + + context 'format html' do + it 'renders snippets page' do + get :snippets, username: user.username + expect(response.status).to eq(200) + expect(response).to render_template('show') + end + end + + context 'format json' do + it 'response with snippets json data' do + get :snippets, username: user.username, format: :json + expect(response.status).to eq(200) + expect(JSON.parse(response.body)).to have_key('html') + end + end + end end |