diff --git a/Gemfile b/Gemfile index e448339456d..db9b95422b4 100644 --- a/Gemfile +++ b/Gemfile @@ -104,6 +104,7 @@ group :test do gem 'capybara' gem 'minitest-ci' gem 'minitest-retry' + gem 'minitest-stub_any_instance' gem 'selenium-webdriver' gem 'vcr' gem 'webmock' diff --git a/Gemfile.lock b/Gemfile.lock index 7aa3c896ffa..e0b8c9bc3c2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -290,6 +290,7 @@ GEM minitest-retry (0.2.2) minitest (>= 5.0) msgpack (1.7.2) + minitest-stub_any_instance (1.0.3) multi_json (1.15.0) multi_xml (0.6.0) multipart-post (2.3.0) @@ -625,6 +626,7 @@ DEPENDENCIES mini_magick minitest-ci minitest-retry + minitest-stub_any_instance net-imap net-pop net-smtp diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 190348f9ab7..e5bddd87767 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -6,6 +6,7 @@ class ApplicationController < ActionController::Base include PolicyHelper helper_method :staging? protect_from_forgery with: :exception + before_action :require_scheduler_inheritation, if: -> { request.path_info.start_with?('/scheduler') } before_action :basic_auth, if: :staging? before_action :test_login, if: :test? before_action :init_user @@ -50,6 +51,10 @@ def require_subscription redirect_to root_path, notice: 'サブスクリプション登録が必要です。' unless current_user&.subscription? end + def require_scheduler_inheritation + head :internal_server_error unless is_a?(SchedulerController) + end + protected def staging? diff --git a/app/controllers/scheduler/daily/fetch_external_entry_controller.rb b/app/controllers/scheduler/daily/fetch_external_entry_controller.rb index 9d28c417dfe..360ced5eadd 100644 --- a/app/controllers/scheduler/daily/fetch_external_entry_controller.rb +++ b/app/controllers/scheduler/daily/fetch_external_entry_controller.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class Scheduler::Daily::FetchExternalEntryController < ApplicationController +class Scheduler::Daily::FetchExternalEntryController < SchedulerController def show ExternalEntry.fetch_and_save_rss_feeds(User.unretired) head :ok diff --git a/app/controllers/scheduler/daily/notify_certain_period_passed_after_last_answer_controller.rb b/app/controllers/scheduler/daily/notify_certain_period_passed_after_last_answer_controller.rb index 8bfb4752fbd..c66537ff7fa 100644 --- a/app/controllers/scheduler/daily/notify_certain_period_passed_after_last_answer_controller.rb +++ b/app/controllers/scheduler/daily/notify_certain_period_passed_after_last_answer_controller.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class Scheduler::Daily::NotifyCertainPeriodPassedAfterLastAnswerController < ApplicationController +class Scheduler::Daily::NotifyCertainPeriodPassedAfterLastAnswerController < SchedulerController def show Question.notify_certain_period_passed_after_last_answer head :ok diff --git a/app/controllers/scheduler_controller.rb b/app/controllers/scheduler_controller.rb index a99ddd0040b..7af6e9f6835 100644 --- a/app/controllers/scheduler_controller.rb +++ b/app/controllers/scheduler_controller.rb @@ -8,7 +8,7 @@ class SchedulerController < ApplicationController protected def require_token - return if ENV['TOKEN'] == params[:token] + return if ENV['TOKEN'].present? && ENV['TOKEN'] == params[:token] head :unauthorized end diff --git a/test/application_system_test_case.rb b/test/application_system_test_case.rb index 31d9439265d..445a50117d3 100644 --- a/test/application_system_test_case.rb +++ b/test/application_system_test_case.rb @@ -8,6 +8,7 @@ require 'supports/report_helper' require 'supports/comment_helper' require 'supports/tag_helper' +require 'supports/mock_env_helper' class ApplicationSystemTestCase < ActionDispatch::SystemTestCase include LoginHelper @@ -17,6 +18,7 @@ class ApplicationSystemTestCase < ActionDispatch::SystemTestCase include ReportHelper include CommentHelper include TagHelper + include MockEnvHelper if ENV['HEADED'] driven_by :selenium, using: :chrome diff --git a/test/integration/scheduler/daily/auto_retire_test.rb b/test/integration/scheduler/daily/auto_retire_test.rb new file mode 100644 index 00000000000..1cab9df0a6c --- /dev/null +++ b/test/integration/scheduler/daily/auto_retire_test.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require 'test_helper' +require 'supports/mock_env_helper' + +class Scheduler::Daily::AutoRetireTest < ActionDispatch::IntegrationTest + include MockEnvHelper + + test 'token evaluation' do + mock_env('TOKEN' => '') do + get scheduler_daily_auto_retire_path(token: '') + assert_response 401 + end + + mock_env('TOKEN' => 'token') do + get scheduler_daily_auto_retire_path(token: 'invalid') + assert_response 401 + + Scheduler::Daily::AutoRetireController.stub_any_instance(:auto_retire) do + get scheduler_daily_auto_retire_path(token: 'token') + assert_response 200 + end + end + end +end diff --git a/test/integration/scheduler/daily/fetch_external_entry_test.rb b/test/integration/scheduler/daily/fetch_external_entry_test.rb new file mode 100644 index 00000000000..bf267fc1e43 --- /dev/null +++ b/test/integration/scheduler/daily/fetch_external_entry_test.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require 'test_helper' +require 'supports/mock_env_helper' + +class Scheduler::Daily::FetchExternalEntryTest < ActionDispatch::IntegrationTest + include MockEnvHelper + + test 'token evaluation' do + mock_env('TOKEN' => '') do + get scheduler_daily_fetch_external_entry_path(token: '') + assert_response 401 + end + + mock_env('TOKEN' => 'token') do + get scheduler_daily_fetch_external_entry_path(token: 'invalid') + assert_response 401 + + ExternalEntry.stub(:fetch_and_save_rss_feeds, nil) do + get scheduler_daily_fetch_external_entry_path(token: 'token') + assert_response 200 + end + end + end +end diff --git a/test/integration/scheduler/daily/notify_certain_period_passed_after_last_answer_test.rb b/test/integration/scheduler/daily/notify_certain_period_passed_after_last_answer_test.rb new file mode 100644 index 00000000000..42228ba7c83 --- /dev/null +++ b/test/integration/scheduler/daily/notify_certain_period_passed_after_last_answer_test.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require 'test_helper' +require 'supports/mock_env_helper' + +class Scheduler::Daily::NotifyCertainPeriodPassedAfterLastAnswerTest < ActionDispatch::IntegrationTest + include MockEnvHelper + + test 'token evaluation' do + mock_env('TOKEN' => '') do + get scheduler_daily_notify_certain_period_passed_after_last_answer_path(token: '') + assert_response 401 + end + + mock_env('TOKEN' => 'token') do + get scheduler_daily_notify_certain_period_passed_after_last_answer_path(token: 'invalid') + assert_response 401 + + Question.stub(:notify_certain_period_passed_after_last_answer, nil) do + get scheduler_daily_notify_certain_period_passed_after_last_answer_path(token: 'token') + assert_response 200 + end + end + end +end diff --git a/test/integration/scheduler/daily/notify_coming_soon_regular_events_test.rb b/test/integration/scheduler/daily/notify_coming_soon_regular_events_test.rb new file mode 100644 index 00000000000..c26e9386aae --- /dev/null +++ b/test/integration/scheduler/daily/notify_coming_soon_regular_events_test.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require 'test_helper' +require 'supports/mock_env_helper' + +class Scheduler::Daily::NotifyComingSoonRegularEventsTest < ActionDispatch::IntegrationTest + include MockEnvHelper + + test 'token evaluation' do + mock_env('TOKEN' => '') do + get scheduler_daily_notify_coming_soon_regular_events_path(token: '') + assert_response 401 + end + + mock_env('TOKEN' => 'token') do + get scheduler_daily_notify_coming_soon_regular_events_path(token: 'invalid') + assert_response 401 + + Scheduler::Daily::NotifyComingSoonRegularEventsController.stub_any_instance(:notify_coming_soon_regular_events) do + get scheduler_daily_notify_coming_soon_regular_events_path(token: 'token') + assert_response 200 + end + end + end +end diff --git a/test/supports/mock_env_helper.rb b/test/supports/mock_env_helper.rb new file mode 100644 index 00000000000..9dfba9f3989 --- /dev/null +++ b/test/supports/mock_env_helper.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +module MockEnvHelper + def mock_env(hash_for_mock, &block) + env_hash = ENV.to_hash.merge(hash_for_mock) + ENV.stub(:[], ->(key) { env_hash[key] }, &block) + end +end diff --git a/test/system/auto_retire_test.rb b/test/system/auto_retire_test.rb index 9d97ebe3d77..a92d55df59d 100644 --- a/test/system/auto_retire_test.rb +++ b/test/system/auto_retire_test.rb @@ -16,7 +16,9 @@ class AutoRetireTest < ApplicationSystemTestCase user = users(:kyuukai) travel_to Time.zone.local(2020, 7, 2, 0, 0, 0) do VCR.use_cassette 'subscription/update' do - visit_with_auth scheduler_daily_auto_retire_path, 'komagata' + mock_env('TOKEN' => 'token') do + visit scheduler_daily_auto_retire_path(token: 'token') + end end assert_equal Date.current, user.reload.retired_on end @@ -49,7 +51,9 @@ class AutoRetireTest < ApplicationSystemTestCase user = users(:kyuukai) travel_to Time.zone.local(2020, 7, 1, 0, 0, 0) do VCR.use_cassette 'subscription/update' do - visit_with_auth scheduler_daily_auto_retire_path, 'komagata' + mock_env('TOKEN' => 'token') do + visit scheduler_daily_auto_retire_path(token: 'token') + end end assert_nil user.reload.retired_on end @@ -64,7 +68,9 @@ class AutoRetireTest < ApplicationSystemTestCase logout travel_to Time.zone.local(2020, 7, 2, 0, 0, 0) do - visit_with_auth scheduler_daily_auto_retire_path, 'komagata' + mock_env('TOKEN' => 'token') do + visit scheduler_daily_auto_retire_path(token: 'token') + end assert_nil user.reload.retired_on end end @@ -76,7 +82,9 @@ class AutoRetireTest < ApplicationSystemTestCase user.update!(retired_on: retired_date) travel_to Time.zone.local(2020, 7, 2, 0, 0, 0) do - visit_with_auth scheduler_daily_auto_retire_path, 'komagata' + mock_env('TOKEN' => 'token') do + visit scheduler_daily_auto_retire_path(token: 'token') + end assert_equal retired_date, user.reload.retired_on end end @@ -89,7 +97,9 @@ class AutoRetireTest < ApplicationSystemTestCase travel_to Time.zone.local(2020, 7, 2, 0, 0, 0) do VCR.use_cassette 'subscription/update' do - visit_with_auth scheduler_daily_auto_retire_path, 'komagata' + mock_env('TOKEN' => 'token') do + visit scheduler_daily_auto_retire_path(token: 'token') + end end assert_equal Date.current, user.reload.retired_on end @@ -106,7 +116,9 @@ class AutoRetireTest < ApplicationSystemTestCase travel_to Time.zone.local(2020, 7, 2, 0, 0, 0) do Discord::Server.stub(:delete_text_channel, true) do VCR.use_cassette 'subscription/update' do - visit_with_auth scheduler_daily_auto_retire_path, 'komagata' + mock_env('TOKEN' => 'token') do + visit scheduler_daily_auto_retire_path(token: 'token') + end end end assert_equal Date.current, user.reload.retired_on @@ -123,7 +135,9 @@ class AutoRetireTest < ApplicationSystemTestCase UserMailer.stub(:auto_retire, stub_postmark_error) do travel_to Time.zone.local(2020, 7, 2, 0, 0, 0) do VCR.use_cassette 'subscription/update' do - visit_with_auth scheduler_daily_auto_retire_path, 'komagata' + mock_env('TOKEN' => 'token') do + visit scheduler_daily_auto_retire_path(token: 'token') + end end assert_equal Date.current, user.reload.retired_on end @@ -140,7 +154,9 @@ class AutoRetireTest < ApplicationSystemTestCase travel_to Time.zone.local(2020, 7, 2, 0, 0, 0) do VCR.use_cassette 'subscription/update' do - visit_with_auth scheduler_daily_auto_retire_path, 'komagata' + mock_env('TOKEN' => 'token') do + visit scheduler_daily_auto_retire_path(token: 'token') + end end assert_equal Date.current, user.reload.retired_on end diff --git a/test/system/external_entries_test.rb b/test/system/external_entries_test.rb index d01a415e1be..fad1bc4406b 100644 --- a/test/system/external_entries_test.rb +++ b/test/system/external_entries_test.rb @@ -13,7 +13,9 @@ class ExternalEntriesTest < ApplicationSystemTestCase assert_difference 'ExternalEntry.count', 26 do VCR.use_cassette 'external_entry/fetch2', vcr_options do VCR.use_cassette 'external_entry/fetch' do - visit_with_auth '/scheduler/daily/fetch_external_entry', 'komagata' + mock_env('TOKEN' => 'token') do + visit scheduler_daily_fetch_external_entry_path(token: 'token') + end end end end diff --git a/test/system/notification/questions_test.rb b/test/system/notification/questions_test.rb index 55b003603c8..a45e63a2b73 100644 --- a/test/system/notification/questions_test.rb +++ b/test/system/notification/questions_test.rb @@ -303,15 +303,23 @@ class Notification::QuestionsTest < ApplicationSystemTestCase ) travel_to Time.zone.local(2022, 11, 6, 0, 0, 0) do - visit_with_auth '/scheduler/daily/notify_certain_period_passed_after_last_answer', 'kimura' - visit '/notifications' - - assert_no_text 'Q&A「テストの質問」のベストアンサーがまだ選ばれていません。' + assert_no_difference 'questioner.notifications.count' do + mock_env('TOKEN' => 'token') do + visit scheduler_daily_notify_certain_period_passed_after_last_answer_path(token: 'token') + end + visit_with_auth '/notifications', 'kimura' + + assert_no_text 'Q&A「テストの質問」のベストアンサーがまだ選ばれていません。' + assert_current_path(notifications_path(_login_name: 'kimura')) + end end + logout travel_to Time.zone.local(2022, 11, 7, 0, 0, 0) do - visit_with_auth '/scheduler/daily/notify_certain_period_passed_after_last_answer', 'kimura' - visit '/notifications' + mock_env('TOKEN' => 'token') do + visit scheduler_daily_notify_certain_period_passed_after_last_answer_path(token: 'token') + end + visit_with_auth '/notifications', 'kimura' assert_text 'Q&A「テストの質問」のベストアンサーがまだ選ばれていません。' end diff --git a/test/system/notification/regular_events_test.rb b/test/system/notification/regular_events_test.rb index 066a620066c..3276488444c 100644 --- a/test/system/notification/regular_events_test.rb +++ b/test/system/notification/regular_events_test.rb @@ -67,7 +67,9 @@ class Notification::RegularEventsTest < ApplicationSystemTestCase headers: { 'Content-Type' => 'application/json' }) travel_to Time.zone.local(2023, 5, 5, 6, 0, 0) do - visit '/scheduler/daily/notify_coming_soon_regular_events' + mock_env('TOKEN' => 'token') do + visit scheduler_daily_notify_coming_soon_regular_events_path(token: 'token') + end end assert_requested(stub_message)