diff options
Diffstat (limited to 'spec/requests/verifies_with_email_spec.rb')
-rw-r--r-- | spec/requests/verifies_with_email_spec.rb | 156 |
1 files changed, 131 insertions, 25 deletions
diff --git a/spec/requests/verifies_with_email_spec.rb b/spec/requests/verifies_with_email_spec.rb index f3f8e4a1a83..cc85ebc7ade 100644 --- a/spec/requests/verifies_with_email_spec.rb +++ b/spec/requests/verifies_with_email_spec.rb @@ -21,6 +21,16 @@ RSpec.describe 'VerifiesWithEmail', :clean_gitlab_redis_sessions, :clean_gitlab_ expect(mail.to).to match_array([user.email]) expect(mail.subject).to eq(s_('IdentityVerification|Verify your identity')) end + + context 'when an unconfirmed verification email exists' do + let(:new_email) { 'new@email' } + let(:user) { create(:user, unconfirmed_email: new_email, confirmation_sent_at: 1.minute.ago) } + + it 'sends a verification instructions email to the unconfirmed email address' do + mail = ActionMailer::Base.deliveries.find { |d| d.to.include?(new_email) } + expect(mail.subject).to eq(s_('IdentityVerification|Verify your identity')) + end + end end shared_examples_for 'prompt for email verification' do @@ -147,12 +157,10 @@ RSpec.describe 'VerifiesWithEmail', :clean_gitlab_redis_sessions, :clean_gitlab_ post(user_session_path(user: { verification_token: 'token' })) end - it_behaves_like 'prompt for email verification' - it 'adds a verification error message' do - expect(response.body) - .to include("You've reached the maximum amount of tries. "\ - 'Wait 10 minutes or send a new code and try again.') + expect(json_response) + .to include('message' => "You've reached the maximum amount of tries. "\ + 'Wait 10 minutes or send a new code and try again.') end end @@ -161,11 +169,10 @@ RSpec.describe 'VerifiesWithEmail', :clean_gitlab_redis_sessions, :clean_gitlab_ post(user_session_path(user: { verification_token: 'invalid_token' })) end - it_behaves_like 'prompt for email verification' - it 'adds a verification error message' do - expect(response.body) - .to include((s_('IdentityVerification|The code is incorrect. Enter it again, or send a new code.'))) + expect(json_response) + .to include('message' => (s_('IdentityVerification|The code is incorrect. '\ + 'Enter it again, or send a new code.'))) end end @@ -175,27 +182,56 @@ RSpec.describe 'VerifiesWithEmail', :clean_gitlab_redis_sessions, :clean_gitlab_ post(user_session_path(user: { verification_token: 'token' })) end - it_behaves_like 'prompt for email verification' - it 'adds a verification error message' do - expect(response.body) - .to include((s_('IdentityVerification|The code has expired. Send a new code and try again.'))) + expect(json_response) + .to include('message' => (s_('IdentityVerification|The code has expired. Send a new code and try again.'))) end end context 'when a valid verification_token param exists' do - before do - post(user_session_path(user: { verification_token: 'token' })) + subject(:submit_token) { post(user_session_path(user: { verification_token: 'token' })) } + + it 'unlocks the user, create logs and records the activity', :freeze_time do + expect { submit_token }.to change { user.reload.unlock_token }.to(nil) + .and change { user.locked_at }.to(nil) + .and change { AuditEvent.count }.by(1) + .and change { AuthenticationEvent.count }.by(1) + .and change { user.last_activity_on }.to(Date.today) + .and change { user.email_reset_offered_at }.to(Time.current) + end + + it 'returns the success status and a redirect path' do + submit_token + expect(json_response).to eq('status' => 'success', 'redirect_path' => users_successful_verification_path) end - it 'unlocks the user' do - user.reload - expect(user.unlock_token).to be_nil - expect(user.locked_at).to be_nil + context 'when an unconfirmed verification email exists' do + before do + user.update!(email: new_email) + end + + let(:new_email) { 'new@email' } + + it 'confirms the email' do + expect { submit_token } + .to change { user.reload.email }.to(new_email) + .and change { user.confirmed_at } + .and change { user.unconfirmed_email }.from(new_email).to(nil) + end end - it 'redirects to the successful verification path' do - expect(response).to redirect_to(users_successful_verification_path) + context 'when email reset has already been offered' do + before do + user.update!(email_reset_offered_at: 1.hour.ago, email: 'new@email') + end + + it 'does not change the email_reset_offered_at field' do + expect { submit_token }.not_to change { user.reload.email_reset_offered_at } + end + + it 'does not confirm the email' do + expect { submit_token }.not_to change { user.reload.email } + end end end @@ -206,8 +242,8 @@ RSpec.describe 'VerifiesWithEmail', :clean_gitlab_redis_sessions, :clean_gitlab_ post user_session_path, params: { user: { login: another_user.username, password: another_user.password } } end - it 'does not redirect to the successful verification path' do - expect(response).not_to redirect_to(users_successful_verification_path) + it 'redirects to the root path' do + expect(response).to redirect_to(root_path) end end end @@ -277,7 +313,6 @@ RSpec.describe 'VerifiesWithEmail', :clean_gitlab_redis_sessions, :clean_gitlab_ end it_behaves_like 'send verification instructions' - it_behaves_like 'prompt for email verification' end context 'when exceeding the rate limit' do @@ -301,8 +336,79 @@ RSpec.describe 'VerifiesWithEmail', :clean_gitlab_redis_sessions, :clean_gitlab_ mail = find_email_for(user) expect(mail).to be_nil end + end + end - it_behaves_like 'prompt for email verification' + describe 'update_email' do + let(:new_email) { 'new@email' } + + subject(:do_request) { patch(users_update_email_path(user: { email: new_email })) } + + context 'when no verification_user_id session variable exists' do + it 'returns 204 No Content' do + do_request + + expect(response).to have_gitlab_http_status(:no_content) + expect(response.body).to be_empty + end + end + + context 'when a verification_user_id session variable exists' do + before do + stub_session(verification_user_id: user.id) + end + + it 'locks the user' do + do_request + + expect(user.reload.unlock_token).not_to be_nil + expect(user.locked_at).not_to be_nil + end + + it 'sends a changed notification to the primary email and verification instructions to the unconfirmed email' do + perform_enqueued_jobs { do_request } + + sent_mails = ActionMailer::Base.deliveries.map { |mail| { mail.to[0] => mail.subject } } + + expect(sent_mails).to match_array([ + { user.reload.unconfirmed_email => s_('IdentityVerification|Verify your identity') }, + { user.email => 'Email Changed' } + ]) + end + + it 'calls the UpdateEmailService and returns a success response' do + expect_next_instance_of(Users::EmailVerification::UpdateEmailService, user: user) do |instance| + expect(instance).to receive(:execute).with(email: new_email).and_call_original + end + + do_request + + expect(json_response).to eq('status' => 'success') + end + end + + context 'when failing to update the email address' do + let(:service_response) do + { + status: 'failure', + reason: 'the reason', + message: 'the message' + } + end + + before do + stub_session(verification_user_id: user.id) + end + + it 'calls the UpdateEmailService and returns an error response' do + expect_next_instance_of(Users::EmailVerification::UpdateEmailService, user: user) do |instance| + expect(instance).to receive(:execute).with(email: new_email).and_return(service_response) + end + + do_request + + expect(json_response).to eq(service_response.with_indifferent_access) + end end end |