discourse/plugins/chat/spec/jobs/regular/chat_notify_mentioned_spec.rb
Martin Brennan c6764d8c74
FIX: Automatically generate category channel slugs (#18879)
This commit automatically ensures that category channels
have slugs when they are created or updated based on the
channel name, category name, or existing slug. The behaviour
has been copied from the Category model.

We also include a backfill here with a simplified version
of Slug.for with deduplication to fill the slugs for already
created Category chat channels.

The channel slug is also now used for chat notifications,
and for the UI and navigation for chat. `slugifyChannel`
is still used, but now does the following fallback:

* Uses channel.slug if it is present
* Uses channel.escapedTitle if it is present
* Uses channel.title if it is present

In future we may want to remove this altogether
and always rely on the slug being present, but this
is currently not possible because we are not generating
slugs for DM channels at this point.
2022-11-09 10:28:31 +10:00

482 lines
16 KiB
Ruby

# frozen_string_literal: true
require "rails_helper"
describe Jobs::ChatNotifyMentioned do
fab!(:user_1) { Fabricate(:user) }
fab!(:user_2) { Fabricate(:user) }
fab!(:public_channel) { Fabricate(:category_channel) }
before do
Group.refresh_automatic_groups!
user_1.reload
user_2.reload
@chat_group = Fabricate(:group, users: [user_1, user_2])
@personal_chat_channel =
Chat::DirectMessageChannelCreator.create!(acting_user: user_1, target_users: [user_1, user_2])
[user_1, user_2].each do |u|
Fabricate(:user_chat_channel_membership, chat_channel: public_channel, user: u)
end
end
def create_chat_message(channel: public_channel, user: user_1)
Fabricate(:chat_message, chat_channel: channel, user: user, created_at: 10.minutes.ago)
end
def track_desktop_notification(
user: user_2,
message:,
to_notify_ids_map:,
already_notified_user_ids: []
)
MessageBus
.track_publish("/chat/notification-alert/#{user.id}") do
subject.execute(
chat_message_id: message.id,
timestamp: message.created_at,
to_notify_ids_map: to_notify_ids_map,
already_notified_user_ids: already_notified_user_ids,
)
end
.first
end
def track_core_notification(user: user_2, message:, to_notify_ids_map:)
subject.execute(
chat_message_id: message.id,
timestamp: message.created_at,
to_notify_ids_map: to_notify_ids_map,
)
Notification.where(user: user, notification_type: Notification.types[:chat_mention]).last
end
describe "scenarios where we should skip sending notifications" do
let(:to_notify_ids_map) { { here_mentions: [user_2.id] } }
it "does nothing if there is a newer version of the message" do
message = create_chat_message
Fabricate(:chat_message_revision, chat_message: message, old_message: "a", new_message: "b")
PostAlerter.expects(:push_notification).never
desktop_notification =
track_desktop_notification(message: message, to_notify_ids_map: to_notify_ids_map)
expect(desktop_notification).to be_nil
created_notification =
Notification.where(user: user_2, notification_type: Notification.types[:chat_mention]).last
expect(created_notification).to be_nil
end
it "does nothing when user is not following the channel" do
message = create_chat_message
UserChatChannelMembership.where(chat_channel: public_channel, user: user_2).update!(
following: false,
)
PostAlerter.expects(:push_notification).never
desktop_notification =
track_desktop_notification(message: message, to_notify_ids_map: to_notify_ids_map)
expect(desktop_notification).to be_nil
created_notification =
Notification.where(user: user_2, notification_type: Notification.types[:chat_mention]).last
expect(created_notification).to be_nil
end
it "does nothing when user doesn't have a membership record" do
message = create_chat_message
UserChatChannelMembership.find_by(chat_channel: public_channel, user: user_2).destroy!
PostAlerter.expects(:push_notification).never
desktop_notification =
track_desktop_notification(message: message, to_notify_ids_map: to_notify_ids_map)
expect(desktop_notification).to be_nil
created_notification =
Notification.where(user: user_2, notification_type: Notification.types[:chat_mention]).last
expect(created_notification).to be_nil
end
it "does nothing if user is included in the already_notified_user_ids" do
message = create_chat_message
PostAlerter.expects(:push_notification).never
desktop_notification =
track_desktop_notification(
message: message,
to_notify_ids_map: to_notify_ids_map,
already_notified_user_ids: [user_2.id],
)
expect(desktop_notification).to be_nil
created_notification =
Notification.where(user: user_2, notification_type: Notification.types[:chat_mention]).last
expect(created_notification).to be_nil
end
it "does nothing if user is not participating in a private channel" do
user_3 = Fabricate(:user)
@chat_group.add(user_3)
to_notify_map = { direct_mentions: [user_3.id] }
message = create_chat_message(channel: @personal_chat_channel)
PostAlerter.expects(:push_notification).never
desktop_notification =
track_desktop_notification(message: message, to_notify_ids_map: to_notify_map)
expect(desktop_notification).to be_nil
created_notification =
Notification.where(user: user_3, notification_type: Notification.types[:chat_mention]).last
expect(created_notification).to be_nil
end
it "skips desktop notifications based on user preferences" do
message = create_chat_message
UserChatChannelMembership.find_by(chat_channel: public_channel, user: user_2).update!(
desktop_notification_level: UserChatChannelMembership::NOTIFICATION_LEVELS[:never],
)
desktop_notification =
track_desktop_notification(message: message, to_notify_ids_map: to_notify_ids_map)
expect(desktop_notification).to be_nil
end
it "skips push notifications based on user preferences" do
message = create_chat_message
UserChatChannelMembership.find_by(chat_channel: public_channel, user: user_2).update!(
mobile_notification_level: UserChatChannelMembership::NOTIFICATION_LEVELS[:never],
)
PostAlerter.expects(:push_notification).never
subject.execute(
chat_message_id: message.id,
timestamp: message.created_at,
to_notify_ids_map: to_notify_ids_map,
)
end
it "skips desktop notifications based on user muting preferences" do
message = create_chat_message
UserChatChannelMembership.find_by(chat_channel: public_channel, user: user_2).update!(
desktop_notification_level: UserChatChannelMembership::NOTIFICATION_LEVELS[:always],
muted: true,
)
desktop_notification =
track_desktop_notification(message: message, to_notify_ids_map: to_notify_ids_map)
expect(desktop_notification).to be_nil
end
it "skips push notifications based on user muting preferences" do
message = create_chat_message
UserChatChannelMembership.find_by(chat_channel: public_channel, user: user_2).update!(
mobile_notification_level: UserChatChannelMembership::NOTIFICATION_LEVELS[:always],
muted: true,
)
PostAlerter.expects(:push_notification).never
subject.execute(
chat_message_id: message.id,
timestamp: message.created_at,
to_notify_ids_map: to_notify_ids_map,
)
end
end
shared_examples "creates different notifications with basic data" do
let(:expected_channel_title) { public_channel.title(user_2) }
it "works for desktop notifications" do
message = create_chat_message
desktop_notification =
track_desktop_notification(message: message, to_notify_ids_map: to_notify_ids_map)
expect(desktop_notification).to be_present
expect(desktop_notification.data[:notification_type]).to eq(Notification.types[:chat_mention])
expect(desktop_notification.data[:username]).to eq(user_1.username)
expect(desktop_notification.data[:tag]).to eq(
Chat::ChatNotifier.push_notification_tag(:mention, public_channel.id),
)
expect(desktop_notification.data[:excerpt]).to eq(message.push_notification_excerpt)
expect(desktop_notification.data[:post_url]).to eq(
"/chat/channel/#{public_channel.id}/#{public_channel.slug}?messageId=#{message.id}",
)
end
it "works for push notifications" do
message = create_chat_message
PostAlerter.expects(:push_notification).with(
user_2,
{
notification_type: Notification.types[:chat_mention],
username: user_1.username,
tag: Chat::ChatNotifier.push_notification_tag(:mention, public_channel.id),
excerpt: message.push_notification_excerpt,
post_url:
"/chat/channel/#{public_channel.id}/#{public_channel.slug}?messageId=#{message.id}",
translated_title: payload_translated_title,
},
)
subject.execute(
chat_message_id: message.id,
timestamp: message.created_at,
to_notify_ids_map: to_notify_ids_map,
)
end
it "works for core notifications" do
message = create_chat_message
created_notification =
track_core_notification(message: message, to_notify_ids_map: to_notify_ids_map)
expect(created_notification).to be_present
expect(created_notification.high_priority).to eq(true)
expect(created_notification.read).to eq(false)
data_hash = created_notification.data_hash
expect(data_hash[:chat_message_id]).to eq(message.id)
expect(data_hash[:chat_channel_id]).to eq(public_channel.id)
expect(data_hash[:mentioned_by_username]).to eq(user_1.username)
expect(data_hash[:is_direct_message_channel]).to eq(false)
expect(data_hash[:chat_channel_title]).to eq(expected_channel_title)
expect(data_hash[:chat_channel_slug]).to eq(public_channel.slug)
chat_mention =
ChatMention.where(notification: created_notification, user: user_2, chat_message: message)
expect(chat_mention).to be_present
end
end
describe "#execute" do
describe "global mention notifications" do
let(:to_notify_ids_map) { { global_mentions: [user_2.id] } }
let(:payload_translated_title) do
I18n.t(
"discourse_push_notifications.popup.chat_mention.other_type",
username: user_1.username,
identifier: "@all",
channel: public_channel.title(user_2),
)
end
include_examples "creates different notifications with basic data"
it "includes global mention specific data to core notifications" do
message = create_chat_message
created_notification =
track_core_notification(message: message, to_notify_ids_map: to_notify_ids_map)
data_hash = created_notification.data_hash
expect(data_hash[:identifier]).to eq("all")
end
it "includes global mention specific data to desktop notifications" do
message = create_chat_message
desktop_notification =
track_desktop_notification(message: message, to_notify_ids_map: to_notify_ids_map)
expect(desktop_notification.data[:translated_title]).to eq(payload_translated_title)
end
context "with private channels" do
it "users a different translated title" do
message = create_chat_message(channel: @personal_chat_channel)
desktop_notification =
track_desktop_notification(message: message, to_notify_ids_map: to_notify_ids_map)
expected_title =
I18n.t(
"discourse_push_notifications.popup.direct_message_chat_mention.other_type",
username: user_1.username,
identifier: "@all",
)
expect(desktop_notification.data[:translated_title]).to eq(expected_title)
end
end
end
describe "here mention notifications" do
let(:to_notify_ids_map) { { here_mentions: [user_2.id] } }
let(:payload_translated_title) do
I18n.t(
"discourse_push_notifications.popup.chat_mention.other_type",
username: user_1.username,
identifier: "@here",
channel: public_channel.title(user_2),
)
end
include_examples "creates different notifications with basic data"
it "includes here mention specific data to core notifications" do
message = create_chat_message
created_notification =
track_core_notification(message: message, to_notify_ids_map: to_notify_ids_map)
data_hash = created_notification.data_hash
expect(data_hash[:identifier]).to eq("here")
end
it "includes here mention specific data to desktop notifications" do
message = create_chat_message
desktop_notification =
track_desktop_notification(message: message, to_notify_ids_map: to_notify_ids_map)
expect(desktop_notification.data[:translated_title]).to eq(payload_translated_title)
end
context "with private channels" do
it "users a different translated title" do
message = create_chat_message(channel: @personal_chat_channel)
desktop_notification =
track_desktop_notification(message: message, to_notify_ids_map: to_notify_ids_map)
expected_title =
I18n.t(
"discourse_push_notifications.popup.direct_message_chat_mention.other_type",
username: user_1.username,
identifier: "@here",
)
expect(desktop_notification.data[:translated_title]).to eq(expected_title)
end
end
end
describe "direct mention notifications" do
let(:to_notify_ids_map) { { direct_mentions: [user_2.id] } }
let(:payload_translated_title) do
I18n.t(
"discourse_push_notifications.popup.chat_mention.direct",
username: user_1.username,
identifier: "",
channel: public_channel.title(user_2),
)
end
include_examples "creates different notifications with basic data"
it "includes here mention specific data to core notifications" do
message = create_chat_message
created_notification =
track_core_notification(message: message, to_notify_ids_map: to_notify_ids_map)
data_hash = created_notification.data_hash
expect(data_hash[:identifier]).to be_nil
end
it "includes here mention specific data to desktop notifications" do
message = create_chat_message
desktop_notification =
track_desktop_notification(message: message, to_notify_ids_map: to_notify_ids_map)
expect(desktop_notification.data[:translated_title]).to eq(payload_translated_title)
end
context "with private channels" do
it "users a different translated title" do
message = create_chat_message(channel: @personal_chat_channel)
desktop_notification =
track_desktop_notification(message: message, to_notify_ids_map: to_notify_ids_map)
expected_title =
I18n.t(
"discourse_push_notifications.popup.direct_message_chat_mention.direct",
username: user_1.username,
identifier: "",
)
expect(desktop_notification.data[:translated_title]).to eq(expected_title)
end
end
end
describe "group mentions" do
let(:to_notify_ids_map) { { @chat_group.name.to_sym => [user_2.id] } }
let(:payload_translated_title) do
I18n.t(
"discourse_push_notifications.popup.chat_mention.other_type",
username: user_1.username,
identifier: "@#{@chat_group.name}",
channel: public_channel.title(user_2),
)
end
include_examples "creates different notifications with basic data"
it "includes here mention specific data to core notifications" do
message = create_chat_message
created_notification =
track_core_notification(message: message, to_notify_ids_map: to_notify_ids_map)
data_hash = created_notification.data_hash
expect(data_hash[:identifier]).to eq(@chat_group.name)
expect(data_hash[:is_group_mention]).to eq(true)
end
it "includes here mention specific data to desktop notifications" do
message = create_chat_message
desktop_notification =
track_desktop_notification(message: message, to_notify_ids_map: to_notify_ids_map)
expect(desktop_notification.data[:translated_title]).to eq(payload_translated_title)
end
context "with private channels" do
it "users a different translated title" do
message = create_chat_message(channel: @personal_chat_channel)
desktop_notification =
track_desktop_notification(message: message, to_notify_ids_map: to_notify_ids_map)
expected_title =
I18n.t(
"discourse_push_notifications.popup.direct_message_chat_mention.other_type",
username: user_1.username,
identifier: "@#{@chat_group.name}",
)
expect(desktop_notification.data[:translated_title]).to eq(expected_title)
end
end
end
end
end