diff --git a/Gemfile b/Gemfile index 1b6f060c4e4..a50142a77b9 100644 --- a/Gemfile +++ b/Gemfile @@ -127,7 +127,6 @@ group :test do gem 'rspec-retry' gem 'scss_lint', require: false gem 'shoulda-matchers', '~> 4.0', require: false - gem 'timecop' gem 'webdrivers', '~> 4.0' gem 'webmock' gem 'zonebie' diff --git a/Gemfile.lock b/Gemfile.lock index 7f93073451a..2c27d0334bc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -631,7 +631,6 @@ GEM thor (1.1.0) thread_safe (0.3.6) tilt (2.0.10) - timecop (0.9.4) tpm-key_attestation (0.10.0) bindata (~> 2.4) openssl-signature_algorithm (~> 1.0) @@ -799,7 +798,6 @@ DEPENDENCIES stringex strong_migrations (>= 0.4.2) subprocess - timecop uglifier (~> 4.2) user_agent_parser valid_email (>= 0.1.3) diff --git a/spec/controllers/account_reset/delete_account_controller_spec.rb b/spec/controllers/account_reset/delete_account_controller_spec.rb index d8b28ce232e..095a86db5c6 100644 --- a/spec/controllers/account_reset/delete_account_controller_spec.rb +++ b/spec/controllers/account_reset/delete_account_controller_spec.rb @@ -88,7 +88,7 @@ expect(@analytics).to receive(:track_event). with(Analytics::ACCOUNT_RESET, properties) - Timecop.travel(Time.zone.now + 2.days) do + travel_to(Time.zone.now + 2.days) do session[:granted_token] = AccountResetRequest.all[0].granted_token delete :delete end @@ -133,7 +133,7 @@ expect(@analytics).to receive(:track_event). with(Analytics::ACCOUNT_RESET, properties) - Timecop.travel(Time.zone.now + 2.days) do + travel_to(Time.zone.now + 2.days) do get :show, params: { token: AccountResetRequest.all[0].granted_token } end diff --git a/spec/controllers/idv/capture_doc_controller_spec.rb b/spec/controllers/idv/capture_doc_controller_spec.rb index c43a25c75e6..68279cb02f9 100644 --- a/spec/controllers/idv/capture_doc_controller_spec.rb +++ b/spec/controllers/idv/capture_doc_controller_spec.rb @@ -51,7 +51,7 @@ context 'with an expired token' do it 'redirects to the root url' do - Timecop.travel(Time.zone.now + 1.day) do + travel_to(Time.zone.now + 1.day) do get :index, params: { 'document-capture-session': session_uuid } end diff --git a/spec/controllers/sign_up/completions_controller_spec.rb b/spec/controllers/sign_up/completions_controller_spec.rb index cade3937051..ff55508addb 100644 --- a/spec/controllers/sign_up/completions_controller_spec.rb +++ b/spec/controllers/sign_up/completions_controller_spec.rb @@ -124,7 +124,7 @@ end describe '#update' do - let(:now) { Time.zone.now } + let(:now) { Time.zone.now.change(usec: 0) } before do stub_analytics @@ -166,7 +166,8 @@ last_consented_at: now, clear_deleted_at: true, ) - Timecop.freeze(now) do + freeze_time do + travel_to(now) patch :update end end @@ -217,7 +218,8 @@ last_consented_at: now, clear_deleted_at: true, ) - Timecop.freeze(now) do + freeze_time do + travel_to(now) patch :update end end diff --git a/spec/controllers/two_factor_authentication/personal_key_verification_controller_spec.rb b/spec/controllers/two_factor_authentication/personal_key_verification_controller_spec.rb index 1db546a827d..47265188ebf 100644 --- a/spec/controllers/two_factor_authentication/personal_key_verification_controller_spec.rb +++ b/spec/controllers/two_factor_authentication/personal_key_verification_controller_spec.rb @@ -31,7 +31,6 @@ profile = create(:profile, :active, :verified, pii: { ssn: '1234' }) user = profile.user raw_key = PersonalKeyGenerator.new(user).create - old_key = user.reload.encrypted_recovery_code_digest stub_sign_in_before_2fa(user) get :show diff --git a/spec/controllers/users/forget_all_browsers_controller_spec.rb b/spec/controllers/users/forget_all_browsers_controller_spec.rb index 30895c52acf..28a066ed116 100644 --- a/spec/controllers/users/forget_all_browsers_controller_spec.rb +++ b/spec/controllers/users/forget_all_browsers_controller_spec.rb @@ -46,7 +46,12 @@ it 'updates the remember_device_revoked_at attribute for the user' do now = Time.zone.now - expect { Timecop.freeze(now) { subject } }.to change { user.remember_device_revoked_at.to_i }. + expect do + freeze_time do + travel_to(now) + subject + end + end.to change { user.remember_device_revoked_at.to_i }. from(original_device_revoked_at.to_i). to(now.to_i) end diff --git a/spec/controllers/users/reset_passwords_controller_spec.rb b/spec/controllers/users/reset_passwords_controller_spec.rb index fba5a9119dd..61e21840b51 100644 --- a/spec/controllers/users/reset_passwords_controller_spec.rb +++ b/spec/controllers/users/reset_passwords_controller_spec.rb @@ -181,7 +181,7 @@ raw_reset_token, db_confirmation_token = Devise.token_generator.generate(User, :reset_password_token) - Timecop.freeze(Time.zone.now) do + freeze_time do user = create( :user, :signed_up, diff --git a/spec/controllers/users/service_provider_revoke_controller_spec.rb b/spec/controllers/users/service_provider_revoke_controller_spec.rb index eeea441c517..1650e53d6a3 100644 --- a/spec/controllers/users/service_provider_revoke_controller_spec.rb +++ b/spec/controllers/users/service_provider_revoke_controller_spec.rb @@ -61,9 +61,14 @@ subject { delete :destroy, params: { sp_id: sp_id } } it 'marks the identity as deleted and redirects' do - expect { Timecop.freeze(now) { subject } }. - to change { @identity.reload.deleted_at&.to_i }. - from(nil).to(now.to_i) + expect do + freeze_time do + travel_to(now) + subject + end + end.to change { @identity.reload.deleted_at&.to_i }. + from(nil).to(now.to_i) + expect(response).to redirect_to(account_connected_accounts_path) end diff --git a/spec/controllers/users/sessions_controller_spec.rb b/spec/controllers/users/sessions_controller_spec.rb index 0a52c214dce..1401afa327a 100644 --- a/spec/controllers/users/sessions_controller_spec.rb +++ b/spec/controllers/users/sessions_controller_spec.rb @@ -97,9 +97,9 @@ expected_time = now + 10 session[:pinged_at] = now - Timecop.travel(Time.zone.now + 10) - get :active - Timecop.return + travel_to(Time.zone.now + 10) do + get :active + end expect(session[:pinged_at].to_i).to be_within(1).of(expected_time.to_i) end diff --git a/spec/decorators/user_decorator_spec.rb b/spec/decorators/user_decorator_spec.rb index 778f6234a97..ad5ae40a5ef 100644 --- a/spec/decorators/user_decorator_spec.rb +++ b/spec/decorators/user_decorator_spec.rb @@ -68,7 +68,7 @@ describe '#lockout_time_remaining' do it 'returns the difference in seconds between otp drift and second_factor_locked_at' do - Timecop.freeze(Time.zone.now) do + freeze_time do user = build_stubbed(:user, second_factor_locked_at: Time.zone.now - 180) user_decorator = UserDecorator.new(user) allow(IdentityConfig.store).to receive(:lockout_period_in_minutes).and_return(8) @@ -80,7 +80,7 @@ describe '#lockout_time_remaining_in_words' do it 'converts lockout_time_remaining to words representing minutes and seconds left' do - Timecop.freeze(Time.zone.now) do + freeze_time do user = build_stubbed(:user, second_factor_locked_at: Time.zone.now - 181) user_decorator = UserDecorator.new(user) allow(IdentityConfig.store).to receive(:lockout_period_in_minutes).and_return(8) diff --git a/spec/features/account_reset/cancel_request_spec.rb b/spec/features/account_reset/cancel_request_spec.rb index c22b4999f78..3548c169c83 100644 --- a/spec/features/account_reset/cancel_request_spec.rb +++ b/spec/features/account_reset/cancel_request_spec.rb @@ -10,7 +10,7 @@ click_button t('account_reset.request.yes_continue') reset_email - Timecop.travel(Time.zone.now + 2.days) do + travel_to(Time.zone.now + 2.days) do AccountReset::GrantRequestsAndSendEmails.new.perform(Time.zone.today) open_last_email click_email_link_matching(/cancel\?token/) diff --git a/spec/features/account_reset/delete_account_spec.rb b/spec/features/account_reset/delete_account_spec.rb index 068c6bd1c21..ebb27e57fd2 100644 --- a/spec/features/account_reset/delete_account_spec.rb +++ b/spec/features/account_reset/delete_account_spec.rb @@ -29,7 +29,7 @@ reset_email - Timecop.travel(Time.zone.now + 2.days) do + travel_to(Time.zone.now + 2.days) do AccountReset::GrantRequestsAndSendEmails.new.perform(Time.zone.today) open_last_email click_email_link_matching(/delete_account\?token/) @@ -86,7 +86,7 @@ reset_email allow(IdentityConfig.store).to receive(:push_notifications_enabled).and_return(true) - Timecop.travel(2.days.from_now) do + travel_to(2.days.from_now) do request = stub_push_notification_request( sp_push_notification_endpoint: push_notification_url, event_type: PushNotification::AccountPurgedEvent::EVENT_TYPE, diff --git a/spec/features/event_disavowal_spec.rb b/spec/features/event_disavowal_spec.rb index 6083d3c96e5..bc713c647a9 100644 --- a/spec/features/event_disavowal_spec.rb +++ b/spec/features/event_disavowal_spec.rb @@ -91,7 +91,7 @@ scenario 'attempting to disavow an event after a long time and the disavowal has expired' do perform_disavowable_password_reset - Timecop.travel 11.days.from_now do + travel_to(11.days.from_now) do open_last_email click_email_link_matching(%r{events/disavow}) diff --git a/spec/features/idv/doc_auth/agreement_step_spec.rb b/spec/features/idv/doc_auth/agreement_step_spec.rb index d81c4bcbbf3..8d48ba33692 100644 --- a/spec/features/idv/doc_auth/agreement_step_spec.rb +++ b/spec/features/idv/doc_auth/agreement_step_spec.rb @@ -82,7 +82,7 @@ def expect_doc_auth_first_step end around do |ex| - Timecop.travel(now) { ex.run } + travel_to(now) { ex.run } end it 'renders the warning banner but no other content' do diff --git a/spec/features/idv/doc_auth/document_capture_step_spec.rb b/spec/features/idv/doc_auth/document_capture_step_spec.rb index 30439bf5aa5..fa51c6a97f8 100644 --- a/spec/features/idv/doc_auth/document_capture_step_spec.rb +++ b/spec/features/idv/doc_auth/document_capture_step_spec.rb @@ -152,7 +152,7 @@ throttle_type: :idv_acuant, ) - Timecop.travel(IdentityConfig.store.acuant_attempt_window_in_minutes.minutes.from_now) do + travel_to(IdentityConfig.store.acuant_attempt_window_in_minutes.minutes.from_now) do sign_in_and_2fa_user(user) complete_doc_auth_steps_before_document_capture_step attach_and_submit_images @@ -238,7 +238,7 @@ throttle_type: :idv_acuant, ) - Timecop.travel(IdentityConfig.store.acuant_attempt_window_in_minutes.minutes.from_now) do + travel_to(IdentityConfig.store.acuant_attempt_window_in_minutes.minutes.from_now) do sign_in_and_2fa_user(user) complete_doc_auth_steps_before_document_capture_step attach_and_submit_images diff --git a/spec/features/idv/doc_auth/send_link_step_spec.rb b/spec/features/idv/doc_auth/send_link_step_spec.rb index 765712dd47d..3cccc3deaa0 100644 --- a/spec/features/idv/doc_auth/send_link_step_spec.rb +++ b/spec/features/idv/doc_auth/send_link_step_spec.rb @@ -84,7 +84,7 @@ throttle_type: :idv_send_link, ) - Timecop.travel(Time.zone.now + idv_send_link_attempt_window_in_minutes.minutes) do + travel_to(Time.zone.now + idv_send_link_attempt_window_in_minutes.minutes + 1) do fill_in :doc_auth_phone, with: '415-555-0199' click_idv_continue expect(page).to have_current_path(idv_doc_auth_link_sent_step) diff --git a/spec/features/idv/doc_auth/verify_step_spec.rb b/spec/features/idv/doc_auth/verify_step_spec.rb index 06f02ff74b1..cc41f348220 100644 --- a/spec/features/idv/doc_auth/verify_step_spec.rb +++ b/spec/features/idv/doc_auth/verify_step_spec.rb @@ -113,7 +113,7 @@ step_name: Idv::Steps::VerifyWaitStepShow, ) - Timecop.travel(IdentityConfig.store.idv_attempt_window_in_hours.hours.from_now) do + travel_to(IdentityConfig.store.idv_attempt_window_in_hours.hours.from_now + 1) do sign_in_and_2fa_user complete_doc_auth_steps_before_verify_step click_idv_continue diff --git a/spec/features/idv/doc_auth/welcome_step_spec.rb b/spec/features/idv/doc_auth/welcome_step_spec.rb index 173a00bf178..7f7e5c88345 100644 --- a/spec/features/idv/doc_auth/welcome_step_spec.rb +++ b/spec/features/idv/doc_auth/welcome_step_spec.rb @@ -74,7 +74,7 @@ def expect_doc_auth_upload_step let(:now) { Time.zone.parse('2020-01-01T12:00:00Z') } around do |ex| - Timecop.travel(now) { ex.run } + travel_to(now) { ex.run } end it 'renders the warning banner but no other content' do diff --git a/spec/features/idv/doc_capture/document_capture_step_spec.rb b/spec/features/idv/doc_capture/document_capture_step_spec.rb index c106c433696..08c8156f437 100644 --- a/spec/features/idv/doc_capture/document_capture_step_spec.rb +++ b/spec/features/idv/doc_capture/document_capture_step_spec.rb @@ -288,7 +288,7 @@ DocAuth::Mock::DocAuthMockClient.reset! - Timecop.travel(IdentityConfig.store.acuant_attempt_window_in_minutes.minutes.from_now) do + travel_to(IdentityConfig.store.acuant_attempt_window_in_minutes.minutes.from_now + 1) do complete_doc_capture_steps_before_first_step(user) attach_and_submit_images @@ -374,7 +374,7 @@ DocAuth::Mock::DocAuthMockClient.reset! - Timecop.travel(IdentityConfig.store.acuant_attempt_window_in_minutes.minutes.from_now) do + travel_to(IdentityConfig.store.acuant_attempt_window_in_minutes.minutes.from_now + 1) do complete_doc_capture_steps_before_first_step(user) attach_and_submit_images diff --git a/spec/features/idv/phone_otp_rate_limiting_spec.rb b/spec/features/idv/phone_otp_rate_limiting_spec.rb index 4391d46a3bd..3caaefa1bc4 100644 --- a/spec/features/idv/phone_otp_rate_limiting_spec.rb +++ b/spec/features/idv/phone_otp_rate_limiting_spec.rb @@ -102,7 +102,7 @@ def expect_rate_limit_to_expire(user) Throttle.where(throttle_type: :idv_acuant).destroy_all retry_minutes = IdentityConfig.store.lockout_period_in_minutes + 1 - Timecop.travel retry_minutes.minutes.from_now do + travel_to(retry_minutes.minutes.from_now) do start_idv_from_sp complete_idv_steps_before_phone_otp_verification_step(user) diff --git a/spec/features/idv/steps/phone_otp_verification_step_spec.rb b/spec/features/idv/steps/phone_otp_verification_step_spec.rb index 68fcc47ff04..2fd4fa3bcce 100644 --- a/spec/features/idv/steps/phone_otp_verification_step_spec.rb +++ b/spec/features/idv/steps/phone_otp_verification_step_spec.rb @@ -34,7 +34,7 @@ start_idv_from_sp complete_idv_steps_before_phone_otp_verification_step - Timecop.travel(expiration_minutes.minutes.from_now) do + travel_to(expiration_minutes.minutes.from_now) do fill_in_code_with_last_phone_otp click_button t('forms.buttons.submit.default') diff --git a/spec/features/multiple_emails/add_email_spec.rb b/spec/features/multiple_emails/add_email_spec.rb index 06e37db3ce9..ceba624a7db 100644 --- a/spec/features/multiple_emails/add_email_spec.rb +++ b/spec/features/multiple_emails/add_email_spec.rb @@ -176,7 +176,7 @@ Capybara.reset_session! - Timecop.travel 25.hours.from_now do + travel_to(25.hours.from_now) do click_on_link_in_confirmation_email expect(page).to have_current_path(root_path) expect(page).to_not have_content(t('devise.confirmations.confirmed_but_sign_in')) diff --git a/spec/features/openid_connect/openid_connect_spec.rb b/spec/features/openid_connect/openid_connect_spec.rb index 8d20e031f5a..5d3a0940bc9 100644 --- a/spec/features/openid_connect/openid_connect_spec.rb +++ b/spec/features/openid_connect/openid_connect_spec.rb @@ -50,7 +50,7 @@ it 'succeeds in forcing login with prompt login and prior session' do user = oidc_end_client_secret_jwt(prompt: 'login') - Timecop.travel((IdentityConfig.store.sp_handoff_bounce_max_seconds + 1).seconds.from_now) do + travel_to((IdentityConfig.store.sp_handoff_bounce_max_seconds + 1).seconds.from_now) do oidc_end_client_secret_jwt(prompt: 'login', user: user) end end diff --git a/spec/features/remember_device/session_expiration_spec.rb b/spec/features/remember_device/session_expiration_spec.rb index 1bf6e8bd95b..e464494cc24 100644 --- a/spec/features/remember_device/session_expiration_spec.rb +++ b/spec/features/remember_device/session_expiration_spec.rb @@ -24,10 +24,10 @@ visit_idp_from_sp_with_ial1(:oidc) request_id = ServiceProviderRequestProxy.last.uuid - Timecop.travel(Devise.timeout_in + 1.minute) do + travel(Devise.timeout_in + 1.minute) do # Simulate being idle on the sign in page long enough for the session to - # be deleted from Redis, but since Redis doesn't respect Timecop, we need - # to expire the session manually. + # be deleted from Redis, but since Redis doesn't respect ActiveSupport::Testing::TimeHelpers, + # we need to expire the session manually. session_store.send(:destroy_session_from_sid, session_cookie.value) # Simulate refreshing the page with JS to avoid a CSRF error visit new_user_session_url(request_id: request_id) diff --git a/spec/features/remember_device/sp_expiration_spec.rb b/spec/features/remember_device/sp_expiration_spec.rb index 3c9ed819717..e6ac970e363 100644 --- a/spec/features/remember_device/sp_expiration_spec.rb +++ b/spec/features/remember_device/sp_expiration_spec.rb @@ -7,7 +7,7 @@ context "#{protocol}: signing in" do it "does not require MFA before #{expiration_time.inspect}" do - Timecop.travel(expiration_time.from_now - 1.day) do + travel_to(expiration_time.from_now - 1.day) do visit_idp_from_sp_with_ial1(protocol) sign_in_user(user) @@ -16,7 +16,7 @@ end it "does require MFA after #{expiration_time.inspect}" do - Timecop.travel(expiration_time.from_now + 1.day) do + travel_to(expiration_time.from_now + 1.day) do visit_idp_from_sp_with_ial1(protocol) sign_in_user(user) @@ -33,7 +33,7 @@ context "#{protocol}: visiting while already signed in" do it "does not require MFA before #{expiration_time.inspect}" do - Timecop.travel(expiration_time.from_now - 1.day) do + travel_to(expiration_time.from_now - 1.day) do sign_in_user(user) visit_idp_from_sp_with_ial1(protocol) @@ -42,7 +42,7 @@ end it "does require MFA after #{expiration_time.inspect}" do - Timecop.travel(expiration_time.from_now + 1.day) do + travel_to(expiration_time.from_now + 1.day) do if expiration_time == 30.days sign_in_live_with_2fa(user) visit_idp_from_sp_with_ial1(protocol) diff --git a/spec/features/remember_device/totp_spec.rb b/spec/features/remember_device/totp_spec.rb index 80417130cdb..fc8f4341a53 100644 --- a/spec/features/remember_device/totp_spec.rb +++ b/spec/features/remember_device/totp_spec.rb @@ -39,7 +39,7 @@ def remember_device_and_sign_out_user context 'update totp' do after do - Timecop.return + travel_back end def remember_device_and_sign_out_user @@ -47,7 +47,7 @@ def remember_device_and_sign_out_user visit account_two_factor_authentication_path page.find('.remove-auth-app').click # Delete click_on t('account.index.totp_confirm_delete') - Timecop.travel 5.seconds.from_now # Travel past the revoked at date from disabling the device + travel_to(10.seconds.from_now) # Travel past the revoked at date from disabling the device click_link "+ #{t('account.index.auth_app_add')}", href: authenticator_setup_url fill_in :code, with: totp_secret_from_page check :remember_device diff --git a/spec/features/reports/omb_fitara_report_spec.rb b/spec/features/reports/omb_fitara_report_spec.rb index 33b263b867d..742e3538208 100644 --- a/spec/features/reports/omb_fitara_report_spec.rb +++ b/spec/features/reports/omb_fitara_report_spec.rb @@ -2,7 +2,7 @@ feature 'OMB Fitara compliance officer runs report' do it 'works in july' do - Timecop.travel Date.new(2019, 7, 2) do + travel_to(Date.new(2019, 7, 2)) do visit sign_up_email_path sign_up_and_2fa_ial1_user @@ -12,7 +12,7 @@ end it 'works in december' do - Timecop.travel Date.new(2019, 12, 2) do + travel_to(Date.new(2019, 12, 2)) do visit sign_up_email_path sign_up_and_2fa_ial1_user @@ -22,7 +22,7 @@ end it 'works in january' do - Timecop.travel Date.new(2019, 1, 2) do + travel_to(Date.new(2019, 1, 2)) do visit sign_up_email_path sign_up_and_2fa_ial1_user @@ -37,7 +37,7 @@ it 'generates paths with date or latest prefix' do expect(Identity::Hostdata).to receive(:env).and_return('ci') - Timecop.travel Date.new(2018, 1, 2) do + travel_to(Date.new(2018, 1, 2)) do expect(Reports::OmbFitaraReport.new.send(:generate_s3_paths, report_name, 'json')). to eq( ['ci/omb-fitara-report/latest.omb-fitara-report.json', diff --git a/spec/features/saml/saml_spec.rb b/spec/features/saml/saml_spec.rb index 521d2330cd1..d26de942e4f 100644 --- a/spec/features/saml/saml_spec.rb +++ b/spec/features/saml/saml_spec.rb @@ -223,10 +223,10 @@ class MockSession; end end it 'redirects to root' do - Timecop.travel(Devise.timeout_in + 1.second) - visit api_saml_logout2021_url - expect(page.current_path).to eq('/') - Timecop.return + travel(Devise.timeout_in + 1.second) do + visit api_saml_logout2021_url + expect(page.current_path).to eq('/') + end end end end diff --git a/spec/features/session/timeout_spec.rb b/spec/features/session/timeout_spec.rb index c4bb9850b12..53c91d96081 100644 --- a/spec/features/session/timeout_spec.rb +++ b/spec/features/session/timeout_spec.rb @@ -42,7 +42,7 @@ sign_in_and_2fa_user timeout_in_minutes = IdentityConfig.store.session_total_duration_timeout_in_minutes.to_i - Timecop.travel (timeout_in_minutes + 1).minutes.from_now do + travel_to((timeout_in_minutes + 1).minutes.from_now) do visit account_path expect(page).to have_current_path(root_path) diff --git a/spec/features/two_factor_authentication/change_factor_spec.rb b/spec/features/two_factor_authentication/change_factor_spec.rb index 813d4a252f1..462b93ea150 100644 --- a/spec/features/two_factor_authentication/change_factor_spec.rb +++ b/spec/features/two_factor_authentication/change_factor_spec.rb @@ -7,11 +7,11 @@ before do user # Sign up the user reauthn_date = (IdentityConfig.store.reauthn_window + 1).seconds.from_now - Timecop.travel reauthn_date + travel_to(reauthn_date) end after do - Timecop.return + travel_back end scenario 'editing password' do @@ -32,22 +32,21 @@ phone_configuration = MfaContext.new(user).phone_configurations.first old_phone = phone_configuration.phone - Timecop.travel(IdentityConfig.store.reauthn_window + 1) do - visit manage_phone_path(id: phone_configuration) - complete_2fa_confirmation_without_entering_otp - click_link t('links.two_factor_authentication.get_another_code') - - expect(Telephony).to have_received(:send_authentication_otp).with( - otp: user.reload.direct_otp, - to: old_phone, - expiration: 10, - channel: :sms, - domain: IdentityConfig.store.domain_name, - ) - - expect(current_path). - to eq login_two_factor_path(otp_delivery_preference: 'sms') - end + travel(IdentityConfig.store.reauthn_window + 1) + visit manage_phone_path(id: phone_configuration) + complete_2fa_confirmation_without_entering_otp + click_link t('links.two_factor_authentication.get_another_code') + + expect(Telephony).to have_received(:send_authentication_otp).with( + otp: user.reload.direct_otp, + to: old_phone, + expiration: 10, + channel: :sms, + domain: IdentityConfig.store.domain_name, + ) + + expect(current_path). + to eq login_two_factor_path(otp_delivery_preference: 'sms') end end end @@ -92,7 +91,7 @@ def submit_correct_otp describe 'attempting to bypass current password entry' do it 'does not allow bypassing this step' do sign_in_and_2fa_user - Timecop.travel(IdentityConfig.store.reauthn_window + 1) do + travel(IdentityConfig.store.reauthn_window + 1) do visit manage_password_path expect(current_path).to eq user_password_confirm_path diff --git a/spec/features/two_factor_authentication/sign_in_spec.rb b/spec/features/two_factor_authentication/sign_in_spec.rb index da7a17ec450..5c665c04c0a 100644 --- a/spec/features/two_factor_authentication/sign_in_spec.rb +++ b/spec/features/two_factor_authentication/sign_in_spec.rb @@ -321,7 +321,7 @@ def attempt_to_bypass_2fa Db::AuthAppConfiguration.create(user, secret, nil, 'foo') otp = generate_totp_code(secret) - Timecop.freeze do + freeze_time do sign_in_user(user) fill_in 'code', with: otp click_submit_default diff --git a/spec/features/users/sign_in_spec.rb b/spec/features/users/sign_in_spec.rb index 657978f5e37..2e3219fe507 100644 --- a/spec/features/users/sign_in_spec.rb +++ b/spec/features/users/sign_in_spec.rb @@ -230,12 +230,12 @@ visit account_path expect(current_path).to eq account_path - Timecop.travel(Devise.timeout_in + 1.minute) + travel(Devise.timeout_in + 1.minute) visit account_path expect(current_path).to eq root_path - Timecop.return + travel_back end scenario 'user session cookie has no explicit expiration time (dies with browser exit)' do @@ -334,10 +334,10 @@ user = sign_in_and_2fa_user click_link(t('links.sign_out'), match: :first) - Timecop.travel(Devise.timeout_in + 1.minute) do + travel(Devise.timeout_in + 1.minute) do expect(page).to_not have_content(t('forms.buttons.continue')) - # Redis doesn't respect Timecop so expire session manually. + # Redis doesn't respect ActiveSupport::Testing::TimeHelpers, so expire session manually. session_store.send(:destroy_session_from_sid, session_cookie.value) fill_in_credentials_and_submit(user.email, user.password) diff --git a/spec/features/users/sign_up_spec.rb b/spec/features/users/sign_up_spec.rb index 5bee5477574..adc5d92a2fe 100644 --- a/spec/features/users/sign_up_spec.rb +++ b/spec/features/users/sign_up_spec.rb @@ -269,7 +269,7 @@ confirmation_token: 'foo', uuid: 'foo', email: email, confirmation_sent_at: Time.zone.now ) - Timecop.travel 1.year.from_now do + travel_to(1.year.from_now) do visit sign_up_email_path submit_form_with_valid_email(email) click_confirmation_link_in_email(email) diff --git a/spec/features/users/totp_management_spec.rb b/spec/features/users/totp_management_spec.rb index ec237101dad..191f863d773 100644 --- a/spec/features/users/totp_management_spec.rb +++ b/spec/features/users/totp_management_spec.rb @@ -83,7 +83,7 @@ click_button 'Submit' # simulate user delay. totp has a 30 second time step - Timecop.travel 30.seconds.from_now do + travel_to(30.seconds.from_now) do click_link "+ #{t('account.index.auth_app_add')}", href: authenticator_setup_url secret = find('#qr-code').text diff --git a/spec/features/visitors/bad_password_spec.rb b/spec/features/visitors/bad_password_spec.rb index c79a76152b2..11d21de25bb 100644 --- a/spec/features/visitors/bad_password_spec.rb +++ b/spec/features/visitors/bad_password_spec.rb @@ -16,7 +16,7 @@ fill_in_credentials_and_submit(bad_email, bad_password) expect(page).to have_content(t('errors.sign_in.bad_password_limit')) end - Timecop.travel IdentityConfig.store.max_bad_passwords_window_in_seconds.seconds.from_now do + travel_to(IdentityConfig.store.max_bad_passwords_window_in_seconds.seconds.from_now) do fill_in_credentials_and_submit(bad_email, bad_password) expect(page).to have_content(error_message) end diff --git a/spec/features/visitors/email_confirmation_spec.rb b/spec/features/visitors/email_confirmation_spec.rb index 255ac6e3b65..48193e8a512 100644 --- a/spec/features/visitors/email_confirmation_spec.rb +++ b/spec/features/visitors/email_confirmation_spec.rb @@ -90,7 +90,7 @@ click_email_link_matching(/confirmation_token/) expect(page).to have_current_path(sign_up_enter_password_path, ignore_query: true) - Timecop.travel 48.hours.from_now do + travel_to(48.hours.from_now) do sign_up_with(email) open_last_email click_email_link_matching(/confirmation_token/) diff --git a/spec/features/visitors/password_recovery_spec.rb b/spec/features/visitors/password_recovery_spec.rb index 4f23709f537..e8017ec0dc0 100644 --- a/spec/features/visitors/password_recovery_spec.rb +++ b/spec/features/visitors/password_recovery_spec.rb @@ -259,7 +259,7 @@ expect(unread_emails_for(email).size).to eq(max_attempts) window_in_minutes = IdentityConfig.store.reset_password_email_window_in_minutes + 1 - Timecop.travel(Time.zone.now + window_in_minutes.minutes) do + travel_to(Time.zone.now + window_in_minutes.minutes) do submit_email_for_password_reset(email) expect(unread_emails_for(email).size).to eq(max_attempts + 1) end diff --git a/spec/features/visitors/resend_email_confirmation_spec.rb b/spec/features/visitors/resend_email_confirmation_spec.rb index e2792feb821..cbd5bc45c90 100644 --- a/spec/features/visitors/resend_email_confirmation_spec.rb +++ b/spec/features/visitors/resend_email_confirmation_spec.rb @@ -34,7 +34,7 @@ expect(unread_emails_for(user.email).size).to eq(max_attempts) window_in_minutes = IdentityConfig.store.reg_unconfirmed_email_window_in_minutes + 1 - Timecop.travel(Time.zone.now + window_in_minutes.minutes) do + travel_to(Time.zone.now + window_in_minutes.minutes) do submit_resend_email_confirmation(email) expect(unread_emails_for(user.email).size).to eq(max_attempts + 1) end diff --git a/spec/features/visitors/sign_up_with_email_spec.rb b/spec/features/visitors/sign_up_with_email_spec.rb index c53a2298129..37deb6ce1f2 100644 --- a/spec/features/visitors/sign_up_with_email_spec.rb +++ b/spec/features/visitors/sign_up_with_email_spec.rb @@ -81,7 +81,7 @@ expect(unread_emails_for(email).size).to eq(starting_count + max_attempts) window_in_minutes = IdentityConfig.store.reg_unconfirmed_email_window_in_minutes + 1 - Timecop.travel(Time.zone.now + window_in_minutes.minutes) do + travel_to(Time.zone.now + window_in_minutes.minutes) do sign_up_with(email) expect(unread_emails_for(email).size).to eq(starting_count + max_attempts + 1) end diff --git a/spec/jobs/reports/iaa_billing_report_spec.rb b/spec/jobs/reports/iaa_billing_report_spec.rb index be73eae5b91..6a545202d7b 100644 --- a/spec/jobs/reports/iaa_billing_report_spec.rb +++ b/spec/jobs/reports/iaa_billing_report_spec.rb @@ -109,11 +109,11 @@ Agreements::IntegrationUsage.delete_all Agreements::Integration.delete_all ServiceProvider.delete_all - Timecop.travel now + travel_to(now) end after do - Timecop.return + travel_back end it 'works with no SPs' do diff --git a/spec/jobs/reports/sp_user_quotas_report_spec.rb b/spec/jobs/reports/sp_user_quotas_report_spec.rb index 9d9902bafc2..5d82b232ed6 100644 --- a/spec/jobs/reports/sp_user_quotas_report_spec.rb +++ b/spec/jobs/reports/sp_user_quotas_report_spec.rb @@ -28,7 +28,7 @@ def expect_report_to_run_correctly_for_fiscal_start_year_month_day(year, month, ) results = [{ issuer: issuer, app_id: app_id, ial2_total: 1, percent_ial2_quota: 0 }].to_json - Timecop.travel Date.new(year, month, day) do + travel_to(Date.new(year, month, day)) do expect(subject.perform(Time.zone.today)).to eq(results) end end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 0c7139cc59e..2b5dec542c4 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -31,6 +31,7 @@ config.use_transactional_fixtures = true config.infer_spec_type_from_file_location! + config.include ActiveSupport::Testing::TimeHelpers config.include EmailSpec::Helpers config.include EmailSpec::Matchers config.include AbstractController::Translation diff --git a/spec/services/account_reset/grant_requests_and_send_emails_spec.rb b/spec/services/account_reset/grant_requests_and_send_emails_spec.rb index de258addddc..3786810906b 100644 --- a/spec/services/account_reset/grant_requests_and_send_emails_spec.rb +++ b/spec/services/account_reset/grant_requests_and_send_emails_spec.rb @@ -79,7 +79,7 @@ def after_waiting_the_full_wait_period days = IdentityConfig.store.account_reset_wait_period_days.days - Timecop.travel(Time.zone.now + days) do + travel_to(Time.zone.now + 1 + days) do yield end end diff --git a/spec/services/funnel/registration/range_registered_count_spec.rb b/spec/services/funnel/registration/range_registered_count_spec.rb index 4e352939c8a..eaf520bf821 100644 --- a/spec/services/funnel/registration/range_registered_count_spec.rb +++ b/spec/services/funnel/registration/range_registered_count_spec.rb @@ -48,7 +48,7 @@ end def register_user(year, month, day) - Timecop.travel Date.new(year, month, day) do + travel_to Date.new(year, month, day) do user = create(:user) user_id = user.id Funnel::Registration::Create.call(user_id) diff --git a/spec/services/funnel/registration/range_submitted_count_spec.rb b/spec/services/funnel/registration/range_submitted_count_spec.rb index 1ab31aa00ef..44b25fa2309 100644 --- a/spec/services/funnel/registration/range_submitted_count_spec.rb +++ b/spec/services/funnel/registration/range_submitted_count_spec.rb @@ -48,7 +48,7 @@ end def submit_user(year, month, day) - Timecop.travel Date.new(year, month, day) do + travel_to Date.new(year, month, day) do user = create(:user) user_id = user.id Funnel::Registration::Create.call(user_id) diff --git a/spec/services/id_token_builder_spec.rb b/spec/services/id_token_builder_spec.rb index 82c8b7bb5ee..43224eb36e4 100644 --- a/spec/services/id_token_builder_spec.rb +++ b/spec/services/id_token_builder_spec.rb @@ -30,7 +30,7 @@ end describe '#id_token' do - subject(:id_token) { Timecop.freeze(now) { builder.id_token } } + subject(:id_token) { builder.id_token } let(:decoded_id_token) do JWT.decode( diff --git a/spec/services/idv/send_phone_confirmation_otp_spec.rb b/spec/services/idv/send_phone_confirmation_otp_spec.rb index ec16816d6d5..14ec8b16e31 100644 --- a/spec/services/idv/send_phone_confirmation_otp_spec.rb +++ b/spec/services/idv/send_phone_confirmation_otp_spec.rb @@ -43,7 +43,7 @@ it 'sends an sms' do allow(Telephony).to receive(:send_confirmation_otp).and_call_original - result = Timecop.freeze(now) { subject.call } + result = travel_to(now) { subject.call } expect(result.success?).to eq(true) @@ -69,7 +69,7 @@ it 'makes a phone call' do allow(Telephony).to receive(:send_confirmation_otp).and_call_original - result = Timecop.freeze(now) { subject.call } + result = travel_to(now) { subject.call } expect(result.success?).to eq(true) diff --git a/spec/services/phone_confirmation/confirmaton_session_spec.rb b/spec/services/phone_confirmation/confirmaton_session_spec.rb index cf6fe547bd6..63793c77982 100644 --- a/spec/services/phone_confirmation/confirmaton_session_spec.rb +++ b/spec/services/phone_confirmation/confirmaton_session_spec.rb @@ -90,7 +90,7 @@ expect(otp_object.expired?).to eq(false) - Timecop.travel 9.minutes.from_now do + travel_to 9.minutes.from_now do expect(otp_object.expired?).to eq(false) end end @@ -98,7 +98,7 @@ it 'returns true if the OTP is expired' do otp_object = described_class.start(phone: '+1 (225) 123-4567', delivery_method: :sms) - Timecop.travel 11.minutes.from_now do + travel_to 11.minutes.from_now do expect(otp_object.expired?).to eq(true) end end diff --git a/spec/support/idv_examples/max_attempts.rb b/spec/support/idv_examples/max_attempts.rb index 1285ea1a0f4..9da48dd026c 100644 --- a/spec/support/idv_examples/max_attempts.rb +++ b/spec/support/idv_examples/max_attempts.rb @@ -33,7 +33,7 @@ first(:link, t('links.sign_out')).click reattempt_interval = (IdentityConfig.store.idv_attempt_window_in_hours + 1).hours - Timecop.travel reattempt_interval do + travel(reattempt_interval) do visit_idp_from_sp_with_ial2(:oidc) sign_in_live_with_2fa(user) diff --git a/spec/support/shared_examples/phone/otp_confirmation.rb b/spec/support/shared_examples/phone/otp_confirmation.rb index 9f5ade3896d..85771b35243 100644 --- a/spec/support/shared_examples/phone/otp_confirmation.rb +++ b/spec/support/shared_examples/phone/otp_confirmation.rb @@ -25,7 +25,7 @@ it 'renders an error if the OTP has expired' do visit_otp_confirmation(delivery_method) - Timecop.travel 11.minutes.from_now do + travel_to(11.minutes.from_now) do fill_in :code, with: last_otp(delivery_method) click_submit_default expect(page).to have_content(t('two_factor_authentication.invalid_otp')) diff --git a/spec/support/shared_examples/phone/rate_limitting.rb b/spec/support/shared_examples/phone/rate_limitting.rb index 1b3e2b2bafd..73a5bf268a5 100644 --- a/spec/support/shared_examples/phone/rate_limitting.rb +++ b/spec/support/shared_examples/phone/rate_limitting.rb @@ -58,7 +58,7 @@ def expect_user_to_be_rate_limitted end def expect_rate_limitting_to_expire - Timecop.travel 6.minutes.from_now do + travel_to(6.minutes.from_now) do visit root_path signin(user.email, user.password || Features::SessionHelper::VALID_PASSWORD) diff --git a/spec/support/shared_examples/remember_device.rb b/spec/support/shared_examples/remember_device.rb index 269a0cfae76..b52cfc8b16f 100644 --- a/spec/support/shared_examples/remember_device.rb +++ b/spec/support/shared_examples/remember_device.rb @@ -10,11 +10,10 @@ days_to_travel = (IdentityConfig.store.remember_device_expiration_hours_aal_1 + 1). hours.from_now - Timecop.travel days_to_travel do - sign_in_user(user) + travel_to(days_to_travel) + sign_in_user(user) - expect_mfa_to_be_required_for_user(user) - end + expect_mfa_to_be_required_for_user(user) end it 'requires 2FA on sign in for another user' do diff --git a/spec/support/shared_examples/sign_in.rb b/spec/support/shared_examples/sign_in.rb index f08ed58d22d..de20ba16e10 100644 --- a/spec/support/shared_examples/sign_in.rb +++ b/spec/support/shared_examples/sign_in.rb @@ -42,9 +42,6 @@ end shared_examples 'visiting 2fa when fully authenticated' do |sp| - before { Timecop.freeze Time.zone.now } - after { Timecop.return } - it 'redirects to SP after visiting a 2fa screen when fully authenticated', email: true do ial1_sign_in_with_personal_key_goes_to_sp(sp) @@ -63,9 +60,6 @@ end shared_examples 'signing in as IAL2 with personal key' do |sp| - before { Timecop.freeze Time.zone.now } - after { Timecop.return } - it 'does not present personal key as an MFA option', :email do user = create_ial2_account_go_back_to_sp_and_sign_out(sp) pii = { ssn: '666-66-1234', dob: '1920-01-01', first_name: 'alice' } @@ -100,9 +94,6 @@ end shared_examples 'signing in as IAL1 with personal key after resetting password' do |sp| - before { Timecop.freeze Time.zone.now } - after { Timecop.return } - it 'redirects to SP', email: true do user = create_ial1_account_go_back_to_sp_and_sign_out(sp) @@ -204,27 +195,25 @@ def personal_key_for_ial2_user(user, pii) end def ial1_sign_in_with_personal_key_goes_to_sp(sp) - Timecop.freeze Time.zone.now do - user = create_ial1_account_go_back_to_sp_and_sign_out(sp) - old_personal_key = PersonalKeyGenerator.new(user).create + user = create_ial1_account_go_back_to_sp_and_sign_out(sp) + old_personal_key = PersonalKeyGenerator.new(user).create - Capybara.reset_sessions! + Capybara.reset_sessions! - visit_idp_from_sp_with_ial1(sp) - fill_in_credentials_and_submit(user.email, 'Val!d Pass w0rd') - choose_another_security_option('personal_key') - enter_personal_key(personal_key: old_personal_key) - click_submit_default - click_agree_and_continue + visit_idp_from_sp_with_ial1(sp) + fill_in_credentials_and_submit(user.email, 'Val!d Pass w0rd') + choose_another_security_option('personal_key') + enter_personal_key(personal_key: old_personal_key) + click_submit_default + click_agree_and_continue - expect(current_url).to eq @saml_authn_request if sp == :saml + expect(current_url).to eq @saml_authn_request if sp == :saml - return unless sp == :oidc + return unless sp == :oidc - redirect_uri = URI(current_url) + redirect_uri = URI(current_url) - expect(redirect_uri.to_s).to start_with('http://localhost:7654/auth/result') - end + expect(redirect_uri.to_s).to start_with('http://localhost:7654/auth/result') end def ial1_sign_in_with_piv_cac_goes_to_sp(sp) diff --git a/spec/views/devise/sessions/new.html.erb_spec.rb b/spec/views/devise/sessions/new.html.erb_spec.rb index a863df87ecb..c8a199b62bd 100644 --- a/spec/views/devise/sessions/new.html.erb_spec.rb +++ b/spec/views/devise/sessions/new.html.erb_spec.rb @@ -160,7 +160,7 @@ end around do |ex| - Timecop.travel(now) { ex.run } + travel_to(now) { ex.run } end it 'renders the warning banner and the normal form' do diff --git a/spec/views/idv/doc_auth/welcome.html.erb_spec.rb b/spec/views/idv/doc_auth/welcome.html.erb_spec.rb index 25f9d9b0295..25093f8d471 100644 --- a/spec/views/idv/doc_auth/welcome.html.erb_spec.rb +++ b/spec/views/idv/doc_auth/welcome.html.erb_spec.rb @@ -68,7 +68,7 @@ end around do |ex| - Timecop.travel(now) { ex.run } + travel_to(now) { ex.run } end it 'renders the warning banner but no other content' do