We're updating core to change TL based access settings to be group based. This requires some updates of tests to work correctly. (The existing test setup gives false positives.)
459 lines
16 KiB
Ruby
459 lines
16 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "rails_helper"
|
|
require_dependency "post_creator"
|
|
require_relative "../dummy_provider"
|
|
|
|
RSpec.describe DiscourseChatIntegration::Manager do
|
|
let(:manager) { ::DiscourseChatIntegration::Manager }
|
|
let(:category) { Fabricate(:category) }
|
|
let(:group) { Fabricate(:group) }
|
|
let(:group2) { Fabricate(:group) }
|
|
let(:topic) { Fabricate(:topic, category_id: category.id) }
|
|
let(:first_post) { Fabricate(:post, topic: topic) }
|
|
let(:second_post) { Fabricate(:post, topic: topic, post_number: 2) }
|
|
|
|
describe ".trigger_notifications" do
|
|
include_context "with dummy provider"
|
|
|
|
let(:chan1) { DiscourseChatIntegration::Channel.create!(provider: "dummy") }
|
|
let(:chan2) { DiscourseChatIntegration::Channel.create!(provider: "dummy") }
|
|
let(:chan3) { DiscourseChatIntegration::Channel.create!(provider: "dummy") }
|
|
|
|
before { SiteSetting.chat_integration_enabled = true }
|
|
|
|
it "should fail gracefully when a provider throws an exception" do
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan1,
|
|
filter: "watch",
|
|
category_id: category.id,
|
|
)
|
|
|
|
# Triggering a ProviderError should set the error_key to the error message
|
|
provider.set_raise_exception(
|
|
DiscourseChatIntegration::ProviderError.new info: { error_key: "hello" }
|
|
)
|
|
manager.trigger_notifications(first_post.id)
|
|
expect(provider.sent_to_channel_ids).to contain_exactly
|
|
expect(DiscourseChatIntegration::Channel.all.first.error_key).to eq("hello")
|
|
|
|
# Triggering a different error should set the error_key to a generic message
|
|
provider.set_raise_exception(StandardError.new "hello")
|
|
manager.trigger_notifications(first_post.id)
|
|
expect(provider.sent_to_channel_ids).to contain_exactly
|
|
expect(DiscourseChatIntegration::Channel.all.first.error_key).to eq(
|
|
"chat_integration.channel_exception",
|
|
)
|
|
|
|
provider.set_raise_exception(nil)
|
|
|
|
manager.trigger_notifications(first_post.id)
|
|
expect(DiscourseChatIntegration::Channel.all.first.error_key.nil?).to be true
|
|
end
|
|
|
|
it "should not send notifications when provider is disabled" do
|
|
SiteSetting.chat_integration_enabled = false
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan1,
|
|
filter: "watch",
|
|
category_id: category.id,
|
|
)
|
|
|
|
manager.trigger_notifications(first_post.id)
|
|
|
|
expect(provider.sent_to_channel_ids).to contain_exactly
|
|
end
|
|
|
|
it "should send a notification to watched and following channels for new topic" do
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan1,
|
|
filter: "watch",
|
|
category_id: category.id,
|
|
)
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan2,
|
|
filter: "follow",
|
|
category_id: category.id,
|
|
)
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan3,
|
|
filter: "mute",
|
|
category_id: category.id,
|
|
)
|
|
|
|
manager.trigger_notifications(first_post.id)
|
|
|
|
expect(provider.sent_to_channel_ids).to contain_exactly(chan1.id, chan2.id)
|
|
end
|
|
|
|
it "should send a notification only to watched for reply" do
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan1,
|
|
filter: "watch",
|
|
category_id: category.id,
|
|
)
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan2,
|
|
filter: "follow",
|
|
category_id: category.id,
|
|
)
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan3,
|
|
filter: "mute",
|
|
category_id: category.id,
|
|
)
|
|
|
|
manager.trigger_notifications(second_post.id)
|
|
|
|
expect(provider.sent_to_channel_ids).to contain_exactly(chan1.id)
|
|
end
|
|
|
|
it "should respect wildcard category settings" do
|
|
DiscourseChatIntegration::Rule.create!(channel: chan1, filter: "watch", category_id: nil)
|
|
|
|
manager.trigger_notifications(first_post.id)
|
|
|
|
expect(provider.sent_to_channel_ids).to contain_exactly(chan1.id)
|
|
end
|
|
|
|
it "should respect mute over watch" do
|
|
DiscourseChatIntegration::Rule.create!(channel: chan1, filter: "watch", category_id: nil) # Wildcard watch
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan1,
|
|
filter: "mute",
|
|
category_id: category.id,
|
|
) # Specific mute
|
|
|
|
manager.trigger_notifications(first_post.id)
|
|
|
|
expect(provider.sent_to_channel_ids).to contain_exactly
|
|
end
|
|
|
|
it "should respect watch over follow" do
|
|
DiscourseChatIntegration::Rule.create!(channel: chan1, filter: "follow", category_id: nil) # Wildcard follow
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan1,
|
|
filter: "watch",
|
|
category_id: category.id,
|
|
) # Specific watch
|
|
|
|
manager.trigger_notifications(second_post.id)
|
|
|
|
expect(provider.sent_to_channel_ids).to contain_exactly(chan1.id)
|
|
end
|
|
|
|
it "should respect thread over watch" do
|
|
DiscourseChatIntegration::Rule.create!(channel: chan1, filter: "watch", category_id: nil) # Wildcard watch
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan1,
|
|
filter: "thread",
|
|
category_id: category.id,
|
|
) # Specific thread
|
|
|
|
manager.trigger_notifications(second_post.id)
|
|
|
|
expect(provider.sent_to_channel_ids).to contain_exactly(chan1.id)
|
|
end
|
|
|
|
it "should not notify about private messages" do
|
|
DiscourseChatIntegration::Rule.create!(channel: chan1, filter: "follow", category_id: nil) # Wildcard watch
|
|
|
|
private_post = Fabricate(:private_message_post)
|
|
|
|
manager.trigger_notifications(private_post.id)
|
|
|
|
expect(provider.sent_to_channel_ids).to contain_exactly
|
|
end
|
|
|
|
it "should work for group pms" do
|
|
DiscourseChatIntegration::Rule.create!(channel: chan1, filter: "watch") # Wildcard watch
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan2,
|
|
type: "group_message",
|
|
filter: "watch",
|
|
group_id: group.id,
|
|
) # Group watch
|
|
|
|
private_post = Fabricate(:private_message_post)
|
|
private_post.topic.invite_group(Fabricate(:user), group)
|
|
|
|
manager.trigger_notifications(private_post.id)
|
|
|
|
expect(provider.sent_to_channel_ids).to contain_exactly(chan2.id)
|
|
end
|
|
|
|
it "should work for pms with multiple groups" do
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan1,
|
|
type: "group_message",
|
|
filter: "watch",
|
|
group_id: group.id,
|
|
)
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan2,
|
|
type: "group_message",
|
|
filter: "watch",
|
|
group_id: group2.id,
|
|
)
|
|
|
|
private_post = Fabricate(:private_message_post)
|
|
private_post.topic.invite_group(Fabricate(:user), group)
|
|
private_post.topic.invite_group(Fabricate(:user), group2)
|
|
|
|
manager.trigger_notifications(private_post.id)
|
|
|
|
expect(provider.sent_to_channel_ids).to contain_exactly(chan1.id, chan2.id)
|
|
end
|
|
|
|
it "should work for group mentions" do
|
|
third_post =
|
|
Fabricate(:post, topic: topic, post_number: 3, raw: "let's mention @#{group.name}")
|
|
|
|
DiscourseChatIntegration::Rule.create!(channel: chan1, filter: "watch") # Wildcard watch
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan2,
|
|
type: "group_message",
|
|
filter: "watch",
|
|
group_id: group.id,
|
|
)
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan3,
|
|
type: "group_mention",
|
|
filter: "watch",
|
|
group_id: group.id,
|
|
)
|
|
|
|
manager.trigger_notifications(third_post.id)
|
|
expect(provider.sent_to_channel_ids).to contain_exactly(chan1.id, chan3.id)
|
|
end
|
|
|
|
it "should give group rule precedence over normal rules" do
|
|
third_post =
|
|
Fabricate(:post, topic: topic, post_number: 3, raw: "let's mention @#{group.name}")
|
|
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan1,
|
|
filter: "mute",
|
|
category_id: category.id,
|
|
) # Mute category
|
|
manager.trigger_notifications(third_post.id)
|
|
expect(provider.sent_to_channel_ids).to contain_exactly
|
|
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan1,
|
|
filter: "watch",
|
|
type: "group_mention",
|
|
group_id: group.id,
|
|
) # Watch mentions
|
|
manager.trigger_notifications(third_post.id)
|
|
expect(provider.sent_to_channel_ids).to contain_exactly(chan1.id)
|
|
end
|
|
|
|
it "should not notify about mentions in private messages" do
|
|
# Group 1 watching for messages on channel 1
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan1,
|
|
filter: "watch",
|
|
type: "group_message",
|
|
group_id: group.id,
|
|
)
|
|
# Group 2 watching for mentions on channel 2
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan2,
|
|
filter: "watch",
|
|
type: "group_mention",
|
|
group_id: group2.id,
|
|
)
|
|
|
|
# Make a private message only accessible to group 1
|
|
private_message = Fabricate(:private_message_post)
|
|
private_message.topic.invite_group(Fabricate(:user), group)
|
|
|
|
# Mention group 2 in the message
|
|
mention_post =
|
|
Fabricate(
|
|
:post,
|
|
topic: private_message.topic,
|
|
post_number: 2,
|
|
raw: "let's mention @#{group2.name}",
|
|
)
|
|
|
|
# We expect that only group 1 receives a notification
|
|
manager.trigger_notifications(mention_post.id)
|
|
expect(provider.sent_to_channel_ids).to contain_exactly(chan1.id)
|
|
end
|
|
|
|
it "should not notify about posts the chat_user cannot see" do
|
|
DiscourseChatIntegration::Rule.create!(channel: chan1, filter: "follow", category_id: nil) # Wildcard watch
|
|
|
|
# Create a group & user
|
|
group = Fabricate(:group, name: "friends")
|
|
user = Fabricate(:user, username: "david")
|
|
group.add(user)
|
|
|
|
# Set the chat_user to the newly created non-admin user
|
|
SiteSetting.chat_integration_discourse_username = "david"
|
|
|
|
# Create a category
|
|
category = Fabricate(:category, name: "Test category")
|
|
topic.category = category
|
|
topic.save!
|
|
|
|
# Restrict category to admins only
|
|
category.set_permissions(Group[:admins] => :full)
|
|
category.save!
|
|
|
|
# Check no notification sent
|
|
manager.trigger_notifications(first_post.id)
|
|
expect(provider.sent_to_channel_ids).to contain_exactly
|
|
|
|
# Now expose category to new user
|
|
category.set_permissions(Group[:friends] => :full)
|
|
category.save!
|
|
|
|
# Check notification sent
|
|
manager.trigger_notifications(first_post.id)
|
|
expect(provider.sent_to_channel_ids).to contain_exactly(chan1.id)
|
|
end
|
|
|
|
describe "With `create_post_for_category_and_tag_changes` enabled" do
|
|
before(:each) { SiteSetting.create_post_for_category_and_tag_changes = true }
|
|
|
|
let(:admin) { Fabricate(:admin) }
|
|
let(:other_topic) { Fabricate(:topic) }
|
|
let(:other_topic_post) { Fabricate(:post, topic: topic) }
|
|
|
|
it "should trigger follow rules for specific categories when topic category changes" do
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan1,
|
|
filter: "follow",
|
|
category_id: category.id,
|
|
)
|
|
|
|
PostRevisor.new(other_topic_post).revise!(admin, category_id: category.id)
|
|
|
|
manager.trigger_notifications(topic.ordered_posts.last.id)
|
|
|
|
expect(provider.sent_to_channel_ids).to contain_exactly(chan1.id)
|
|
end
|
|
|
|
it "shouldn't trigger follow rules with wildcard category match" do
|
|
DiscourseChatIntegration::Rule.create!(channel: chan1, filter: "follow", category_id: nil)
|
|
|
|
PostRevisor.new(other_topic_post).revise!(admin, category_id: category.id)
|
|
|
|
manager.trigger_notifications(topic.ordered_posts.last.id)
|
|
|
|
expect(provider.sent_to_channel_ids).to contain_exactly
|
|
end
|
|
end
|
|
|
|
describe "with tags enabled" do
|
|
let(:tag) { Fabricate(:tag, name: "gsoc") }
|
|
let(:tagged_topic) { Fabricate(:topic, category_id: category.id, tags: [tag]) }
|
|
let(:tagged_first_post) { Fabricate(:post, topic: tagged_topic) }
|
|
|
|
before(:each) { SiteSetting.tagging_enabled = true }
|
|
|
|
it "should still work for rules without any tags specified" do
|
|
DiscourseChatIntegration::Rule.create!(channel: chan1, filter: "follow", category_id: nil) # Wildcard watch
|
|
|
|
manager.trigger_notifications(first_post.id)
|
|
manager.trigger_notifications(tagged_first_post.id)
|
|
|
|
expect(provider.sent_to_channel_ids).to contain_exactly(chan1.id, chan1.id)
|
|
end
|
|
|
|
it "should only match tagged topics when rule has tags" do
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan1,
|
|
filter: "follow",
|
|
category_id: category.id,
|
|
tags: [tag.name],
|
|
)
|
|
|
|
manager.trigger_notifications(first_post.id)
|
|
manager.trigger_notifications(tagged_first_post.id)
|
|
|
|
expect(provider.sent_to_channel_ids).to contain_exactly(chan1.id)
|
|
end
|
|
|
|
describe "with create_small_action_post_for_tag_changes enabled" do
|
|
fab!(:admin) { Fabricate(:admin, refresh_auto_groups: true) }
|
|
fab!(:additional_tag) { Fabricate(:tag) }
|
|
|
|
before { SiteSetting.create_post_for_category_and_tag_changes = true }
|
|
|
|
def set_new_tags_and_return_small_action_post(tags)
|
|
PostRevisor.new(tagged_first_post).revise!(admin, tags: tags)
|
|
|
|
tagged_topic.ordered_posts.last
|
|
end
|
|
|
|
it "should notify when rule is set up for tag additions for a category with no tag filter" do
|
|
post = set_new_tags_and_return_small_action_post([tag.name, additional_tag.name])
|
|
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan1,
|
|
filter: "tag_added",
|
|
category_id: category.id,
|
|
)
|
|
|
|
manager.trigger_notifications(post.id)
|
|
expect(provider.sent_to_channel_ids).to contain_exactly(chan1.id)
|
|
end
|
|
|
|
it "notifies when topic has a tag added that matches the rule" do
|
|
post = set_new_tags_and_return_small_action_post([tag.name, additional_tag.name])
|
|
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan1,
|
|
filter: "tag_added",
|
|
category_id: category.id,
|
|
tags: [additional_tag.name],
|
|
)
|
|
|
|
manager.trigger_notifications(post.id)
|
|
expect(provider.sent_to_channel_ids).to contain_exactly(chan1.id)
|
|
end
|
|
|
|
it "doesn't notify when a new regular post is created" do
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan1,
|
|
filter: "tag_added",
|
|
category_id: nil,
|
|
tags: [tag.name],
|
|
)
|
|
|
|
post = Fabricate(:post, topic: tagged_topic)
|
|
manager.trigger_notifications(post.id)
|
|
expect(provider.sent_to_channel_ids).to contain_exactly
|
|
end
|
|
|
|
it "doesn't notify when topic has an unchanged tag present in the rule, even if a new tag is added" do
|
|
post = set_new_tags_and_return_small_action_post([tag.name, additional_tag.name])
|
|
|
|
DiscourseChatIntegration::Rule.create!(
|
|
channel: chan1,
|
|
filter: "tag_added",
|
|
category_id: category.id,
|
|
tags: [tag.name],
|
|
)
|
|
|
|
manager.trigger_notifications(post.id)
|
|
expect(provider.sent_to_channel_ids).to contain_exactly
|
|
end
|
|
|
|
it "doesn't notify for small action 'tags_changed' posts unless a matching rule exists" do
|
|
post = set_new_tags_and_return_small_action_post([additional_tag.name])
|
|
|
|
DiscourseChatIntegration::Rule.create!(channel: chan1, filter: "watch", category_id: nil) # Wildcard watch
|
|
|
|
manager.trigger_notifications(post.id)
|
|
expect(provider.sent_to_channel_ids).to contain_exactly
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|