0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-08 17:53:55 +08:00
discourse/spec/services/upcoming_changes/action/backfill_notified_events_spec.rb
Martin Brennan 4de06a006b
FIX: Do not notify new sites or plugins enabled of old upcoming changes (#42045)
For upcoming changes, we were having a problem where we
were notifying admins of upcoming changes in brand new sites.
A previous fix 2e5afb46e2f5c0547bc298b2bd1a9c39e813dc17 tried
to remedy this, but since it relies on the `new_site?` method, which
isn't true after 1 hour, the next time the scheduled notifications are
run for an admin they will be sent them even if their site is relatively
new.

This commit attempts to conclusively fix the issue by inserting
upcoming change `admins_notified_automatic_promotion` and
`admins_notified_available_change` events via `BackfillNotifiedEvents`
for changes that exist in particular statuses when the site is first
created. These events will have `event_data: {"backfilled" => true}`
to distinguish them from others.

It also fixes an adjacent issue where an admin was notified of a
plugin's upcoming changes as soon as they enable the plugin,
which isn't useful as the intent of upcoming changes is to notify
of changes for things the admin has already been using.

**Before this change, on brand new site with current upcoming change
state**

<img width="401" height="429" alt="image"
src="https://github.com/user-attachments/assets/a89cd641-59aa-4c48-a57c-9692021df176"
/>

**After this change**

No notification to show :) But when I moved an upcoming change to `beta`
it showed
the notification for the enabled upcoming change correctly:

<img width="378" height="174" alt="image"
src="https://github.com/user-attachments/assets/20e4096f-e83f-4c06-970d-a9b43561b12e"
/>
2026-07-30 09:51:08 +10:00

133 lines
3.7 KiB
Ruby
Vendored

# frozen_string_literal: true
RSpec.describe UpcomingChanges::Action::BackfillNotifiedEvents do
let(:change_names) do
%i[enable_upload_debug_mode show_user_menu_avatars enable_experimental_admin_ui_grouped_filters]
end
before do
SiteSetting.promote_upcoming_changes_on_status = :beta
mock_upcoming_change_metadata(
{
# Below the "available" threshold (alpha), so not notifiable yet.
enable_upload_debug_mode: {
impact: "other,developers",
status: :experimental,
impact_type: "other",
impact_role: "developers",
},
# At the "available" threshold.
show_user_menu_avatars: {
impact: "feature,all_members",
status: :alpha,
impact_type: "feature",
impact_role: "all_members",
},
# At/above the promotion threshold.
enable_experimental_admin_ui_grouped_filters: {
impact: "feature,admins",
status: :stable,
impact_type: "feature",
impact_role: "admins",
},
},
)
scoped_events.delete_all
end
def scoped_events
UpcomingChangeEvent.where(upcoming_change_name: change_names)
end
def event_types_for(change_name)
scoped_events.where(upcoming_change_name: change_name).pluck(:event_type).map(&:to_sym)
end
describe ".call" do
subject(:result) { described_class.call(upcoming_change_names: change_names) }
it "records every change as added" do
result
expect(scoped_events.where(event_type: :added).pluck(:upcoming_change_name)).to match_array(
change_names.map(&:to_s),
)
end
it "does not mark a change below the available threshold as notified about" do
result
expect(event_types_for(:enable_upload_debug_mode)).to contain_exactly(:added)
end
it "marks a change at the available threshold as notified about availability" do
result
expect(event_types_for(:show_user_menu_avatars)).to contain_exactly(
:added,
:admins_notified_available_change,
)
end
it "marks a change at the promotion threshold as notified about promotion" do
result
expect(event_types_for(:enable_experimental_admin_ui_grouped_filters)).to contain_exactly(
:added,
:admins_notified_automatic_promotion,
)
end
it "does not promote anything itself" do
result
expect(scoped_events.where(event_type: :automatically_promoted)).to be_empty
end
it "returns the changes it backfilled" do
expect(result).to match_array(change_names)
end
it "is idempotent" do
described_class.call(change_names: change_names)
expect { result }.not_to change { scoped_events.count }
end
it "does not duplicate events that already exist" do
UpcomingChangeEvent.create!(event_type: :added, upcoming_change_name: :show_user_menu_avatars)
result
expect(event_types_for(:show_user_menu_avatars)).to contain_exactly(
:added,
:admins_notified_available_change,
)
end
context "when no change names are given" do
subject(:result) { described_class.call(upcoming_change_names: []) }
it "does nothing" do
expect { result }.not_to change { UpcomingChangeEvent.count }
end
end
context "when change names are not passed" do
subject(:result) { described_class.call }
it "backfills every upcoming change on the site" do
result
expect(
UpcomingChangeEvent.where(
event_type: :added,
upcoming_change_name: SiteSetting.upcoming_change_site_settings,
).count,
).to eq(SiteSetting.upcoming_change_site_settings.count)
end
end
end
end