From 43414abf834306d2fc5d4840bf8486c16db7b8b3 Mon Sep 17 00:00:00 2001 From: Gabriel Grubba <70247653+Grubba27@users.noreply.github.com> Date: Wed, 27 Nov 2024 14:16:29 -0300 Subject: [PATCH] FIX: `TopicTagsChanged` trigger not working with multiple tags (#29961) * FIX: `TopicTagsChanged` trigger not working with multiple tags The check for when had multiple tags was being exclusive, you had to have all tags to trigger the automation, now it's inclusive, you can trigger the automation if you have any of the tags. * DEV: add specs for when having multiple categories * DEV: changed to use unions and intersections for tags added more tests to check for multiple tags --- .../discourse_automation/event_handlers.rb | 8 +- .../spec/triggers/topic_tags_changed_spec.rb | 109 ++++++++++++++++++ 2 files changed, 111 insertions(+), 6 deletions(-) diff --git a/plugins/automation/lib/discourse_automation/event_handlers.rb b/plugins/automation/lib/discourse_automation/event_handlers.rb index 1a2447fb34f..0ce2903efa5 100644 --- a/plugins/automation/lib/discourse_automation/event_handlers.rb +++ b/plugins/automation/lib/discourse_automation/event_handlers.rb @@ -239,12 +239,8 @@ module DiscourseAutomation watching_tags = automation.trigger_field("watching_tags") if watching_tags["value"] - should_skip = false - watching_tags["value"].each do |tag| - should_skip = true if !removed_tags.empty? && !removed_tags.include?(tag) - should_skip = true if !added_tags.empty? && !added_tags.include?(tag) - end - next if should_skip + changed_tags = (removed_tags | added_tags) + next if (changed_tags & watching_tags["value"]).empty? end automation.trigger!( diff --git a/plugins/automation/spec/triggers/topic_tags_changed_spec.rb b/plugins/automation/spec/triggers/topic_tags_changed_spec.rb index 0572c4d12f4..a0474ea4cc8 100644 --- a/plugins/automation/spec/triggers/topic_tags_changed_spec.rb +++ b/plugins/automation/spec/triggers/topic_tags_changed_spec.rb @@ -82,6 +82,66 @@ describe DiscourseAutomation::Triggers::TOPIC_TAGS_CHANGED do end end + context "when watching a few cool tags" do + fab!(:cool_tag_2) { Fabricate(:tag) } + fab!(:cool_tag_3) { Fabricate(:tag) } + + before do + automation.upsert_field!( + "watching_tags", + "tags", + { value: [cool_tag.name, cool_tag_2.name, cool_tag_3.name] }, + target: "trigger", + ) + automation.reload + end + + it "should fire the trigger if any tag is added" do + topic_0 = Fabricate(:topic, user: user, tags: [], category: category) + + list = + capture_contexts do + DiscourseTagging.tag_topic_by_names(topic_0, Guardian.new(user), [cool_tag.name]) + end + + expect(list.length).to eq(1) + expect(list[0]["kind"]).to eq(DiscourseAutomation::Triggers::TOPIC_TAGS_CHANGED) + end + + it "should fire the trigger if any tag is removed" do + topic_0 = Fabricate(:topic, user: user, tags: [cool_tag], category: category) + + list = + capture_contexts { DiscourseTagging.tag_topic_by_names(topic_0, Guardian.new(user), []) } + + expect(list.length).to eq(1) + expect(list[0]["kind"]).to eq(DiscourseAutomation::Triggers::TOPIC_TAGS_CHANGED) + end + + it "should not fire if the tag is not present" do + topic_0 = Fabricate(:topic, user: user, tags: [], category: category) + + list = + capture_contexts do + DiscourseTagging.tag_topic_by_names(topic_0, Guardian.new(user), [bad_tag.name]) + end + + expect(list.length).to eq(0) + end + + it "should fire the trigger if a tag is add and one is removed" do + topic_0 = Fabricate(:topic, user: user, tags: [cool_tag], category: category) + + list = + capture_contexts do + DiscourseTagging.tag_topic_by_names(topic_0, Guardian.new(user), [cool_tag_2.name]) + end + + expect(list.length).to eq(1) + expect(list[0]["kind"]).to eq(DiscourseAutomation::Triggers::TOPIC_TAGS_CHANGED) + end + end + context "when watching a category" do before do automation.upsert_field!( @@ -128,6 +188,55 @@ describe DiscourseAutomation::Triggers::TOPIC_TAGS_CHANGED do end end + context "when watching a few categories" do + fab!(:category_2) { Fabricate(:category) } + fab!(:category_3) { Fabricate(:category) } + + before do + automation.upsert_field!( + "watching_categories", + "categories", + { value: [category.id, category_2.id, category_3.id] }, + target: "trigger", + ) + automation.reload + end + + it "should fire the trigger if any tag is added" do + topic_0 = Fabricate(:topic, user: user, tags: [], category: category) + topic_1 = Fabricate(:topic, user: user, tags: [], category: category_2) + + list = + capture_contexts do + DiscourseTagging.tag_topic_by_names(topic_0, Guardian.new(user), [bad_tag.name]) + DiscourseTagging.tag_topic_by_names(topic_1, Guardian.new(user), [bad_tag.name]) + end + + expect(list.length).to eq(2) + expect(list[0]["kind"]).to eq(DiscourseAutomation::Triggers::TOPIC_TAGS_CHANGED) + end + + it "should fire the trigger if any tag is removed" do + topic_0 = Fabricate(:topic, user: user, tags: [cool_tag], category: category) + + list = + capture_contexts { DiscourseTagging.tag_topic_by_names(topic_0, Guardian.new(user), []) } + expect(list.length).to eq(1) + expect(list[0]["kind"]).to eq(DiscourseAutomation::Triggers::TOPIC_TAGS_CHANGED) + end + + it "should not fire if not the watching category" do + topic_0 = Fabricate(:topic, user: user, tags: [], category: Fabricate(:category)) + + list = + capture_contexts do + DiscourseTagging.tag_topic_by_names(topic_0, Guardian.new(user), [cool_tag.name]) + end + + expect(list.length).to eq(0) + end + end + context "when without any watching tags or categories" do it "should fire the trigger if the tag is added" do topic_0 = Fabricate(:topic, user: user, tags: [], category: category)