mirror of
https://github.com/discourse/discourse.git
synced 2026-08-06 13:08:40 +08:00
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"
/>
345 lines
12 KiB
Ruby
Vendored
345 lines
12 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
RSpec.describe UpcomingChanges::NotifyPromotions do
|
|
describe ".call" do
|
|
subject(:result) { described_class.call }
|
|
|
|
fab!(:admin)
|
|
fab!(:admin_2, :admin)
|
|
|
|
let(:enable_upload_debug_mode_status) { :stable }
|
|
let(:show_user_menu_avatars_status) { :beta }
|
|
|
|
before do
|
|
# No upcoming change notifications are sent for new sites
|
|
UpcomingChanges.stubs(:should_notify_admins?).returns(true)
|
|
SiteSetting.promote_upcoming_changes_on_status = :stable
|
|
SiteSetting.stubs(:upcoming_change_site_settings).returns(
|
|
%i[enable_upload_debug_mode show_user_menu_avatars],
|
|
)
|
|
|
|
mock_upcoming_change_metadata(
|
|
{
|
|
enable_upload_debug_mode: {
|
|
impact: "other,developers",
|
|
status: enable_upload_debug_mode_status,
|
|
impact_type: "other",
|
|
impact_role: "developers",
|
|
},
|
|
show_user_menu_avatars: {
|
|
impact: "feature,all_members",
|
|
status: show_user_menu_avatars_status,
|
|
impact_type: "feature",
|
|
impact_role: "all_members",
|
|
},
|
|
},
|
|
)
|
|
end
|
|
|
|
context "when there is an error when trying to process a change" do
|
|
before do
|
|
StaffActionLogger
|
|
.any_instance
|
|
.stubs(:log_upcoming_change_toggle)
|
|
.raises(StandardError, "test error")
|
|
end
|
|
|
|
it "returns the errors" do
|
|
expect(result[:change_notification_statuses]).to match(
|
|
enable_upload_debug_mode: {
|
|
success: false,
|
|
error: "test error",
|
|
error_key: :unexpected_error,
|
|
backtrace: a_kind_of(Array),
|
|
},
|
|
show_user_menu_avatars: {
|
|
success: false,
|
|
error: "Setting show_user_menu_avatars does not meet or exceed the promotion status",
|
|
error_key: :does_not_meet_or_exceed_promotion_status,
|
|
},
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when everything is ok" do
|
|
it { is_expected.to run_successfully }
|
|
|
|
it "returns a state of all settings as success or failure, along with the related error message" do
|
|
expect(result[:change_notification_statuses]).to match(
|
|
enable_upload_debug_mode: {
|
|
success: true,
|
|
},
|
|
show_user_menu_avatars: {
|
|
success: false,
|
|
error: "Setting show_user_menu_avatars does not meet or exceed the promotion status",
|
|
error_key: :does_not_meet_or_exceed_promotion_status,
|
|
},
|
|
)
|
|
end
|
|
|
|
it "logs the change context in the staff action log" do
|
|
expect { result }.to change {
|
|
UserHistory.where(
|
|
action: UserHistory.actions[:upcoming_change_toggled],
|
|
subject: "enable_upload_debug_mode",
|
|
).count
|
|
}.by(1)
|
|
|
|
expect(UserHistory.last.context).to eq(
|
|
I18n.t(
|
|
"staff_action_logs.upcoming_changes.log_promoted",
|
|
change_status: UpcomingChanges.change_status(:enable_upload_debug_mode).to_s.titleize,
|
|
base_path: Discourse.base_path,
|
|
),
|
|
)
|
|
end
|
|
|
|
it "notifies admins about the upcoming change" do
|
|
expect { result }.to change {
|
|
Notification
|
|
.where(
|
|
notification_type: Notification.types[:upcoming_change_automatically_promoted],
|
|
user_id: [admin.id, admin_2.id],
|
|
)
|
|
.where("data::text LIKE ?", "%enable_upload_debug_mode%")
|
|
.count
|
|
}.by(2)
|
|
|
|
notification = Notification.where("data::text LIKE ?", "%enable_upload_debug_mode%").last
|
|
data = JSON.parse(notification.data)
|
|
expect(data["upcoming_change_names"]).to eq(["enable_upload_debug_mode"])
|
|
expect(data["upcoming_change_humanized_names"]).to eq(["Enable upload debug mode"])
|
|
expect(data["count"]).to eq(1)
|
|
end
|
|
|
|
it "creates an admins_notified_automatic_promotion event" do
|
|
expect { result }.to change {
|
|
UpcomingChangeEvent.where(
|
|
event_type: :admins_notified_automatic_promotion,
|
|
upcoming_change_name: :enable_upload_debug_mode,
|
|
).count
|
|
}.by(1)
|
|
end
|
|
|
|
it "triggers DiscourseEvent for the promoted setting" do
|
|
events = DiscourseEvent.track_events { result }
|
|
event =
|
|
events.find do |e|
|
|
e[:event_name] == :upcoming_change_enabled &&
|
|
e[:params].first == :enable_upload_debug_mode
|
|
end
|
|
|
|
expect(event).to be_present
|
|
expect(event[:params]).to eq([:enable_upload_debug_mode])
|
|
end
|
|
|
|
context "when multiple settings meet promotion criteria" do
|
|
let(:show_user_menu_avatars_status) { :stable }
|
|
|
|
it "processes all eligible settings into consolidated notifications" do
|
|
result
|
|
|
|
notifications =
|
|
Notification.where(
|
|
notification_type: Notification.types[:upcoming_change_automatically_promoted],
|
|
user_id: [admin.id, admin_2.id],
|
|
)
|
|
expect(notifications.count).to eq(2)
|
|
|
|
data = JSON.parse(notifications.first.data)
|
|
expect(data["upcoming_change_names"]).to contain_exactly(
|
|
"enable_upload_debug_mode",
|
|
"show_user_menu_avatars",
|
|
)
|
|
expect(data["count"]).to eq(2)
|
|
end
|
|
|
|
it "creates events for all promoted settings" do
|
|
expect { result }.to change {
|
|
UpcomingChangeEvent.where(
|
|
event_type: :admins_notified_automatic_promotion,
|
|
upcoming_change_name: %i[enable_upload_debug_mode show_user_menu_avatars],
|
|
).count
|
|
}.by(2)
|
|
end
|
|
|
|
it "triggers DiscourseEvent for all promoted settings" do
|
|
events = DiscourseEvent.track_events { result }
|
|
promoted_events = events.select { |e| e[:event_name] == :upcoming_change_enabled }
|
|
|
|
expect(promoted_events.length).to eq(2)
|
|
expect(promoted_events.map { |e| e[:params].first }).to contain_exactly(
|
|
:enable_upload_debug_mode,
|
|
:show_user_menu_avatars,
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when there are no upcoming changes" do
|
|
before { SiteSetting.stubs(:upcoming_change_site_settings).returns([]) }
|
|
|
|
it "does not create any notifications" do
|
|
expect { result }.not_to change { Notification.count }
|
|
end
|
|
|
|
it "does not trigger any events" do
|
|
events = DiscourseEvent.track_events { result }
|
|
expect(events.select { |e| e[:event_name] == :upcoming_change_enabled }).to be_empty
|
|
end
|
|
end
|
|
|
|
context "when settings do not meet promotion status" do
|
|
let(:enable_upload_debug_mode_status) { :beta }
|
|
let(:show_user_menu_avatars_status) { :alpha }
|
|
|
|
it "does not create any notifications" do
|
|
expect { result }.not_to change { Notification.count }
|
|
end
|
|
|
|
it "does not trigger any events" do
|
|
events = DiscourseEvent.track_events { result }
|
|
expect(events.select { |e| e[:event_name] == :upcoming_change_enabled }).to be_empty
|
|
end
|
|
|
|
it "returns the correct error and error key" do
|
|
expect(result[:change_notification_statuses][:enable_upload_debug_mode]).to match(
|
|
success: false,
|
|
error: "Setting enable_upload_debug_mode does not meet or exceed the promotion status",
|
|
error_key: :does_not_meet_or_exceed_promotion_status,
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when settings have already been promoted" do
|
|
before do
|
|
UpcomingChangeEvent.create!(
|
|
event_type: :automatically_promoted,
|
|
upcoming_change_name: :enable_upload_debug_mode,
|
|
acting_user: Discourse.system_user,
|
|
)
|
|
end
|
|
|
|
it "does not notify admins again for the already-promoted setting" do
|
|
expect { result }.not_to change {
|
|
Notification
|
|
.where(notification_type: Notification.types[:upcoming_change_automatically_promoted])
|
|
.where("data::text LIKE ?", "%enable_upload_debug_mode%")
|
|
.count
|
|
}
|
|
end
|
|
|
|
it "does not trigger event for the already-promoted setting" do
|
|
events = DiscourseEvent.track_events { result }
|
|
expect(
|
|
events.select do |e|
|
|
e[:event_name] == :upcoming_change_enabled &&
|
|
e[:params].first == :enable_upload_debug_mode
|
|
end,
|
|
).to be_empty
|
|
end
|
|
|
|
it "returns the correct error and error key" do
|
|
expect(result[:change_notification_statuses][:enable_upload_debug_mode]).to match(
|
|
success: false,
|
|
error: "Setting enable_upload_debug_mode has already been promoted",
|
|
error_key: :already_promoted,
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when settings are marked as already notified about, but not promoted" do
|
|
before do
|
|
UpcomingChangeEvent.create!(
|
|
event_type: :admins_notified_automatic_promotion,
|
|
upcoming_change_name: :enable_upload_debug_mode,
|
|
acting_user: Discourse.system_user,
|
|
)
|
|
end
|
|
|
|
it "does not notify admins" do
|
|
expect { result }.not_to change {
|
|
Notification
|
|
.where(notification_type: Notification.types[:upcoming_change_automatically_promoted])
|
|
.where("data::text LIKE ?", "%enable_upload_debug_mode%")
|
|
.count
|
|
}
|
|
end
|
|
|
|
it "still promotes the change, so its side effects run" do
|
|
events = DiscourseEvent.track_events { result }
|
|
|
|
expect(
|
|
events.select do |e|
|
|
e[:event_name] == :upcoming_change_enabled &&
|
|
e[:params].first == :enable_upload_debug_mode
|
|
end,
|
|
).to be_present
|
|
expect(
|
|
UpcomingChangeEvent.exists?(
|
|
event_type: :automatically_promoted,
|
|
upcoming_change_name: :enable_upload_debug_mode,
|
|
),
|
|
).to eq(true)
|
|
end
|
|
end
|
|
|
|
context "when a change should not be displayed on this site" do
|
|
before do
|
|
UpcomingChanges::ConditionalDisplay.stubs(
|
|
:should_display_enable_upload_debug_mode?,
|
|
).returns(false)
|
|
end
|
|
|
|
it "does not notify admins for the hidden setting" do
|
|
expect { result }.not_to change {
|
|
Notification
|
|
.where(notification_type: Notification.types[:upcoming_change_automatically_promoted])
|
|
.where("data::text LIKE ?", "%enable_upload_debug_mode%")
|
|
.count
|
|
}
|
|
end
|
|
|
|
it "returns the correct error and error key" do
|
|
expect(result[:change_notification_statuses][:enable_upload_debug_mode]).to match(
|
|
success: false,
|
|
error:
|
|
"Setting enable_upload_debug_mode is not displayed on this site, skipping promotion notification",
|
|
error_key: :should_not_be_displayed,
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when settings are opted out" do
|
|
before { SiteSetting.enable_upload_debug_mode = false }
|
|
|
|
it "does not notify admins for opted-out settings" do
|
|
expect { result }.not_to change {
|
|
Notification
|
|
.where(notification_type: Notification.types[:upcoming_change_automatically_promoted])
|
|
.where("data::text LIKE ?", "%enable_upload_debug_mode%")
|
|
.count
|
|
}
|
|
end
|
|
|
|
it "does not trigger event for opted-out settings" do
|
|
events = DiscourseEvent.track_events { result }
|
|
expect(
|
|
events.select do |e|
|
|
e[:event_name] == :upcoming_change_enabled &&
|
|
e[:params].first == :enable_upload_debug_mode
|
|
end,
|
|
).to be_empty
|
|
end
|
|
|
|
it "returns the correct error and error key" do
|
|
expect(result[:change_notification_statuses][:enable_upload_debug_mode]).to match(
|
|
success: false,
|
|
error:
|
|
"Setting enable_upload_debug_mode has been manually opted in or out by an admin, we did not notify admins about promotion",
|
|
error_key: :already_manually_toggled,
|
|
)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|