From c5cd9bda484ef8ebe9fdd49beb9b4f54740a1f50 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 31 Jan 2025 03:08:56 -0500 Subject: [PATCH] Convert `auth/passwords` spec controller->system/request (#33790) --- .../auth/passwords_controller_spec.rb | 102 ------------------ spec/requests/auth/passwords_spec.rb | 34 ++++++ spec/system/auth/passwords_spec.rb | 83 ++++++++++++++ 3 files changed, 117 insertions(+), 102 deletions(-) delete mode 100644 spec/controllers/auth/passwords_controller_spec.rb create mode 100644 spec/requests/auth/passwords_spec.rb create mode 100644 spec/system/auth/passwords_spec.rb diff --git a/spec/controllers/auth/passwords_controller_spec.rb b/spec/controllers/auth/passwords_controller_spec.rb deleted file mode 100644 index 90095ac4b8..0000000000 --- a/spec/controllers/auth/passwords_controller_spec.rb +++ /dev/null @@ -1,102 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe Auth::PasswordsController do - include Devise::Test::ControllerHelpers - - describe 'GET #new' do - it 'returns http success' do - request.env['devise.mapping'] = Devise.mappings[:user] - get :new - expect(response).to have_http_status(200) - end - end - - describe 'GET #edit' do - let(:user) { Fabricate(:user) } - - before do - request.env['devise.mapping'] = Devise.mappings[:user] - end - - context 'with valid reset_password_token' do - it 'returns http success' do - token = user.send_reset_password_instructions - - get :edit, params: { reset_password_token: token } - - expect(response).to have_http_status(200) - end - end - - context 'with invalid reset_password_token' do - it 'redirects to #new' do - get :edit, params: { reset_password_token: 'some_invalid_value' } - expect(response).to redirect_to subject.new_password_path(subject.send(:resource_name)) - end - end - end - - describe 'POST #update' do - let(:user) { Fabricate(:user) } - let(:password) { 'reset0password' } - - before do - request.env['devise.mapping'] = Devise.mappings[:user] - end - - context 'with valid reset_password_token' do - let!(:session_activation) { Fabricate(:session_activation, user: user) } - let!(:access_token) { Fabricate(:access_token, resource_owner_id: user.id) } - let!(:web_push_subscription) { Fabricate(:web_push_subscription, access_token: access_token) } - - before do - token = user.send_reset_password_instructions - - post :update, params: { user: { password: password, password_confirmation: password, reset_password_token: token } } - end - - it 'resets the password' do - expect(response) - .to redirect_to '/auth/sign_in' - - # Change password - expect(User.find(user.id)) - .to be_present - .and be_valid_password(password) - - # Deactivate session - expect(user.session_activations.count) - .to eq 0 - expect { session_activation.reload } - .to raise_error(ActiveRecord::RecordNotFound) - - # Revoke tokens - expect(Doorkeeper::AccessToken.active_for(user).count) - .to eq 0 - - # Remove push subs - expect(Web::PushSubscription.where(user: user).or(Web::PushSubscription.where(access_token: access_token)).count) - .to eq 0 - expect { web_push_subscription.reload } - .to raise_error(ActiveRecord::RecordNotFound) - end - end - - context 'with invalid reset_password_token' do - before do - post :update, params: { user: { password: password, password_confirmation: password, reset_password_token: 'some_invalid_value' } } - end - - it 'renders reset password and retains password' do - expect(response) - .to render_template(:new) - - expect(User.find(user.id)) - .to be_present - .and be_external_or_valid_password(user.password) - end - end - end -end diff --git a/spec/requests/auth/passwords_spec.rb b/spec/requests/auth/passwords_spec.rb new file mode 100644 index 0000000000..feefd94587 --- /dev/null +++ b/spec/requests/auth/passwords_spec.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Auth Passwords' do + describe 'GET /auth/password/edit' do + context 'with invalid reset_password_token' do + it 'redirects to #new' do + get edit_user_password_path, params: { reset_password_token: 'some_invalid_value' } + + expect(response) + .to redirect_to new_user_password_path + end + end + end + + describe 'PUT /auth/password' do + let(:user) { Fabricate(:user) } + let(:password) { 'reset0password' } + + context 'with invalid reset_password_token' do + it 'renders reset password and retains password' do + put user_password_path, params: { user: { password: password, password_confirmation: password, reset_password_token: 'some_invalid_value' } } + + expect(response.body) + .to include(I18n.t('auth.set_new_password')) + + expect(User.find(user.id)) + .to be_present + .and be_external_or_valid_password(user.password) + end + end + end +end diff --git a/spec/system/auth/passwords_spec.rb b/spec/system/auth/passwords_spec.rb new file mode 100644 index 0000000000..42733b2521 --- /dev/null +++ b/spec/system/auth/passwords_spec.rb @@ -0,0 +1,83 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Auth Passwords' do + let(:user) { Fabricate :user } + let!(:session_activation) { Fabricate(:session_activation, user: user) } + let!(:access_token) { Fabricate(:access_token, resource_owner_id: user.id) } + let!(:web_push_subscription) { Fabricate(:web_push_subscription, access_token: access_token) } + + describe 'Resetting a password', :inline_jobs do + let(:new_password) { 'New.Pass.123' } + + before { allow(Devise).to receive(:pam_authentication).and_return(false) } # Avoid the "seamless external" path + + it 'initiates reset, sends link, resets password from form, clears data' do + visit new_user_password_path + expect(page) + .to have_title(I18n.t('auth.reset_password')) + + submit_email_reset + expect(page) + .to have_title(I18n.t('auth.set_new_password')) + + set_new_password + expect(page) + .to have_title(I18n.t('auth.login')) + + # Change password + expect(User.find(user.id)) + .to be_present + .and be_valid_password(new_password) + + # Deactivate session + expect(user_session_count) + .to eq(0) + expect { session_activation.reload } + .to raise_error(ActiveRecord::RecordNotFound) + + # Revoke tokens + expect(user_token_count) + .to eq(0) + + # Remove push subs + expect(push_subs_count) + .to eq(0) + expect { web_push_subscription.reload } + .to raise_error(ActiveRecord::RecordNotFound) + end + + def submit_email_reset + fill_in 'user_email', with: user.email + click_on I18n.t('auth.reset_password') + open_last_email + visit_in_email(I18n.t('devise.mailer.reset_password_instructions.action')) + end + + def set_new_password + fill_in 'user_password', with: new_password + fill_in 'user_password_confirmation', with: new_password + click_on I18n.t('auth.set_new_password') + end + + def user_session_count + user + .session_activations + .count + end + + def user_token_count + Doorkeeper::AccessToken + .active_for(user) + .count + end + + def push_subs_count + Web::PushSubscription + .where(user: user) + .or(Web::PushSubscription.where(access_token: access_token)) + .count + end + end +end