discourse-chat-integration/spec/services/manager_spec.rb

174 lines
6.6 KiB
Ruby
Raw Normal View History

require 'rails_helper'
require_dependency 'post_creator'
require_relative '../dummy_provider'
RSpec.describe DiscourseChat::Manager do
let(:manager) {::DiscourseChat::Manager}
let(:category) {Fabricate(:category)}
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 "dummy provider"
let(:chan1){DiscourseChat::Channel.create!(provider:'dummy')}
let(:chan2){DiscourseChat::Channel.create!(provider:'dummy')}
let(:chan3){DiscourseChat::Channel.create!(provider:'dummy')}
before do
SiteSetting.chat_integration_enabled = true
end
it "should fail gracefully when a provider throws an exception" do
DiscourseChat::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(DiscourseChat::ProviderError.new info: {error_key:"hello"})
manager.trigger_notifications(first_post.id)
expect(provider.sent_to_channel_ids).to contain_exactly()
expect(DiscourseChat::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(DiscourseChat::Channel.all.first.error_key).to eq('chat_integration.channel_exception')
provider.set_raise_exception(nil)
manager.trigger_notifications(first_post.id)
expect(DiscourseChat::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
DiscourseChat::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
DiscourseChat::Rule.create!(channel: chan1, filter: 'watch', category_id:category.id )
DiscourseChat::Rule.create!(channel: chan2, filter: 'follow', category_id:category.id )
DiscourseChat::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
DiscourseChat::Rule.create!(channel: chan1, filter: 'watch', category_id:category.id )
DiscourseChat::Rule.create!(channel: chan2, filter: 'follow', category_id:category.id )
DiscourseChat::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
DiscourseChat::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
DiscourseChat::Rule.create!(channel: chan1, filter: 'watch', category_id: nil ) # Wildcard watch
DiscourseChat::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
DiscourseChat::Rule.create!(channel: chan1, filter: 'follow', category_id: nil ) # Wildcard watch
DiscourseChat::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 not notify about private messages" do
DiscourseChat::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 not notify about posts the chat_user cannot see" do
DiscourseChat::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 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) do
SiteSetting.tagging_enabled = true
end
it 'should still work for rules without any tags specified' do
DiscourseChat::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
DiscourseChat::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
end
end
end