discourse/spec/multisite/upcoming_changes_spec.rb
Martin Brennan dd0da69c15
DEV: Fix spec cleanup issues for upcoming changes (#39024)
Fixes two bugs in `clear_mocked_upcoming_change_metadata` /
`mock_upcoming_change_metadata`:

  1. .blank? vs .nil? — {}.blank? is true, so when the original metadata
     was an empty hash (no real upcoming changes loaded in test), the
     clear function returned early without restoring. Fixed by changing
     to .nil?.
  2. Nested mock overwrites original — The `permanent_upcoming_changes`
     describe block in upcoming_changes_spec.rb calls
     `mock_upcoming_change_metadata` a second time in its own before
block. This overwrote `@original_upcoming_changes_metadata` with the
     already-mocked state from the outer before. When clear ran after
     the last example (if it happened to be one from that nested block),
     it restored to the contaminated state instead of the true original.
     Fixed by changing = to ||= so the original is only captured on the
     first call.

Fixes spec failures like this we are seeing:

```
Error encountered while processing /admin/users/1695/revoke_moderation.json.
  NoMethodError: undefined method 'alpha_setting' for class SiteSetting
    ...(1 framework line(s) excluded)
    /__w/discourse/discourse/lib/upcoming_changes.rb:151:in 'Kernel#public_send'
    /__w/discourse/discourse/lib/upcoming_changes.rb:151:in 'UpcomingChanges.enabled_for_user?'
    /__w/discourse/discourse/app/models/user.rb:1971:in 'User#upcoming_change_enabled?'
    /__w/discourse/discourse/lib/upcoming_changes.rb:205:in 'block in UpcomingChanges.stats_for_user'
```
2026-04-01 14:15:02 +10:00

98 lines
3.3 KiB
Ruby

# frozen_string_literal: true
RSpec.describe "Multisite UpcomingChanges cache", type: :multisite do
before do
mock_upcoming_change_metadata(
{
enable_upload_debug_mode: {
impact: "other,developers",
status: :permanent,
impact_type: "other",
impact_role: "developers",
},
},
)
Rails.stubs(:public_path).returns(File.join(Rails.root, "spec", "fixtures"))
end
after do
%w[default second].each do |site|
RailsMultisite::ConnectionManagement.with_connection(site) do
Discourse.cache.delete(UpcomingChanges.current_statuses_cache_key)
Discourse.cache.delete(UpcomingChanges.permanent_upcoming_changes_cache_key)
end
end
end
it "keeps current_statuses tied to each site's upcoming_change_events" do
test_multisite_connection("default") do
Discourse.cache.delete(UpcomingChanges.current_statuses_cache_key)
UpcomingChangeEvent.where(upcoming_change_name: "enable_upload_debug_mode").delete_all
UpcomingChangeEvent.create!(
event_type: :status_changed,
upcoming_change_name: "enable_upload_debug_mode",
event_data: {
"previous_value" => "stable",
"new_value" => "permanent",
},
)
expect(UpcomingChanges.current_statuses["enable_upload_debug_mode"][:status]).to eq(
"permanent",
)
end
test_multisite_connection("second") do
Discourse.cache.delete(UpcomingChanges.current_statuses_cache_key)
UpcomingChangeEvent.where(upcoming_change_name: "enable_upload_debug_mode").delete_all
expect(UpcomingChanges.current_statuses).to eq({})
end
end
it "caches current_statuses on the default site" do
test_multisite_connection("default") do
Discourse.cache.delete(UpcomingChanges.current_statuses_cache_key)
UpcomingChangeEvent.create!(
event_type: :status_changed,
upcoming_change_name: "multisite_cache_setting",
event_data: {
"previous_value" => nil,
"new_value" => "beta",
},
)
allow(DB).to receive(:query).and_call_original
2.times { UpcomingChanges.current_statuses }
expect(DB).to have_received(:query).once
end
end
it "caches current_statuses on the second site" do
test_multisite_connection("second") do
Discourse.cache.delete(UpcomingChanges.current_statuses_cache_key)
allow(DB).to receive(:query).and_call_original
2.times { UpcomingChanges.current_statuses }
expect(DB).to have_received(:query).once
end
end
it "caches permanent_upcoming_changes on the default site" do
test_multisite_connection("default") do
Discourse.cache.delete(UpcomingChanges.permanent_upcoming_changes_cache_key)
allow(UpcomingChanges::List).to receive(:call).and_call_original
2.times { UpcomingChanges.permanent_upcoming_changes }
expect(UpcomingChanges::List).to have_received(:call).once
end
end
it "caches permanent_upcoming_changes on the second site" do
test_multisite_connection("second") do
Discourse.cache.delete(UpcomingChanges.permanent_upcoming_changes_cache_key)
allow(UpcomingChanges::List).to receive(:call).and_call_original
2.times { UpcomingChanges.permanent_upcoming_changes }
expect(UpcomingChanges::List).to have_received(:call).once
end
end
end