discourse/spec/jobs/run_problem_check_spec.rb
Ted Johansson 0c875cb4d5
DEV: Make problem check registration more explicit (#26413)
Previously the problem check registry simply looked at the subclasses of ProblemCheck. This was causing some confusion in environments where eager loading is not enabled, as the registry would appear empty as a result of the classes never being referenced (and thus never loaded.)

This PR changes the approach to a more explicit one. I followed other implementations (bookmarkable and hashtag autocomplete.) As a bonus, this now has a neat plugin entry point as well.
2024-03-28 14:00:47 +08:00

163 lines
4.6 KiB
Ruby

# frozen_string_literal: true
RSpec.describe Jobs::RunProblemCheck do
after { Discourse.redis.flushdb }
context "when there are problems" do
around do |example|
ProblemCheck::TestCheck =
Class.new(ProblemCheck) do
self.perform_every = 30.minutes
self.max_retries = 0
def call
[
ProblemCheck::Problem.new("Big problem"),
ProblemCheck::Problem.new(
"Yuge problem",
priority: "high",
identifier: "config_is_a_mess",
),
]
end
end
stub_const(ProblemCheck, "CORE_PROBLEM_CHECKS", [ProblemCheck::TestCheck], &example)
ProblemCheck.send(:remove_const, "TestCheck")
end
it "adds the messages to the Redis problems array" do
described_class.new.execute(check_identifier: :test_check)
problems = AdminDashboardData.load_found_scheduled_check_problems
expect(problems.map(&:to_s)).to contain_exactly("Big problem", "Yuge problem")
end
end
context "with multiple problems with the same identifier" do
around do |example|
ProblemCheck::TestCheck =
Class.new(ProblemCheck) do
self.perform_every = 30.minutes
self.max_retries = 0
def call
[
ProblemCheck::Problem.new(
"Yuge problem",
priority: "high",
identifier: "config_is_a_mess",
),
ProblemCheck::Problem.new(
"Nasty problem",
priority: "high",
identifier: "config_is_a_mess",
),
]
end
end
stub_const(ProblemCheck, "CORE_PROBLEM_CHECKS", [ProblemCheck::TestCheck], &example)
ProblemCheck.send(:remove_const, "TestCheck")
end
it "does not add the same problem twice" do
described_class.new.execute(check_identifier: :test_check)
problems = AdminDashboardData.load_found_scheduled_check_problems
expect(problems.map(&:to_s)).to match_array(["Yuge problem"])
end
end
context "when there are retries remaining" do
around do |example|
ProblemCheck::TestCheck =
Class.new(ProblemCheck) do
self.perform_every = 30.minutes
self.max_retries = 2
def call
[ProblemCheck::Problem.new("Yuge problem")]
end
end
stub_const(ProblemCheck, "CORE_PROBLEM_CHECKS", [ProblemCheck::TestCheck], &example)
ProblemCheck.send(:remove_const, "TestCheck")
end
it "does not yet update the problem check tracker" do
expect {
described_class.new.execute(check_identifier: :test_check, retry_count: 1)
}.not_to change { ProblemCheckTracker.where("blips > ?", 0).count }
end
it "schedules a retry" do
expect_enqueued_with(
job: :run_problem_check,
args: {
check_identifier: :test_check,
retry_count: 1,
},
) { described_class.new.execute(check_identifier: :test_check) }
end
end
context "when there are no retries remaining" do
around do |example|
ProblemCheck::TestCheck =
Class.new(ProblemCheck) do
self.perform_every = 30.minutes
self.max_retries = 1
def call
[ProblemCheck::Problem.new("Yuge problem")]
end
end
stub_const(ProblemCheck, "CORE_PROBLEM_CHECKS", [ProblemCheck::TestCheck], &example)
ProblemCheck.send(:remove_const, "TestCheck")
end
it "updates the problem check tracker" do
expect {
described_class.new.execute(check_identifier: :test_check, retry_count: 1)
}.to change { ProblemCheckTracker.where("blips > ?", 0).count }.by(1)
end
it "does not schedule a retry" do
expect_not_enqueued_with(job: :run_problem_check) do
described_class.new.execute(check_identifier: :test_check, retry_count: 1)
end
end
end
context "when the check unexpectedly errors out" do
around do |example|
ProblemCheck::TestCheck =
Class.new(ProblemCheck) do
self.max_retries = 1
def call
raise StandardError.new("Something went wrong")
end
end
stub_const(ProblemCheck, "CORE_PROBLEM_CHECKS", [ProblemCheck::TestCheck], &example)
ProblemCheck.send(:remove_const, "TestCheck")
end
it "does not add a problem to the Redis array" do
described_class.new.execute(check_identifier: :test_check)
expect(AdminDashboardData.load_found_scheduled_check_problems).to be_empty
end
end
end