FEATURE: Show an error message if regex is invalid (#13164)

FEATURE: Show an error message if regex is invalid (#13164)

The server cannot always determine when a watched word regular expression is invalid and this commit implements the check on the client side.

diff --git a/app/assets/javascripts/admin/addon/controllers/admin-watched-words-action.js b/app/assets/javascripts/admin/addon/controllers/admin-watched-words-action.js
index 323eaad..d84d806 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-watched-words-action.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-watched-words-action.js
@@ -27,6 +27,17 @@ export default Controller.extend({
     return this.findAction(actionName);
   },
 
+  @discourseComputed("currentAction.words.[]")
+  regexpError(words) {
+    for (const { regexp, word } of words) {
+      try {
+        RegExp(regexp);
+      } catch {
+        return I18n.t("admin.watched_words.invalid_regex", { word });
+      }
+    }
+  },
+
   @discourseComputed("actionNameKey")
   actionDescription(actionNameKey) {
     return I18n.t("admin.watched_words.action_descriptions." + actionNameKey);
diff --git a/app/assets/javascripts/admin/addon/templates/watched-words-action.hbs b/app/assets/javascripts/admin/addon/templates/watched-words-action.hbs
index 92a328a..3f6ce7d 100644
--- a/app/assets/javascripts/admin/addon/templates/watched-words-action.hbs
+++ b/app/assets/javascripts/admin/addon/templates/watched-words-action.hbs
@@ -1,3 +1,7 @@
+{{#if regexpError}}
+  <div class="alert alert-error">{{regexpError}}</div>
+{{/if}}
+
 <div class="watched-word-controls">
   {{d-button
     class="btn-default download-link"
diff --git a/app/assets/javascripts/discourse/tests/acceptance/admin-watched-words-test.js b/app/assets/javascripts/discourse/tests/acceptance/admin-watched-words-test.js
index 4094f6b..8d55953 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/admin-watched-words-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/admin-watched-words-test.js
@@ -12,6 +12,8 @@ acceptance("Admin - Watched Words", function (needs) {
   test("list words in groups", async function (assert) {
     await visit("/admin/customize/watched_words/action/block");
 
+    assert.equal(find(".admin-watched-words .alert-error").length, 0);
+
     assert.ok(
       !exists(".watched-words-list"),
       "Don't show bad words by default."
@@ -100,3 +102,35 @@ acceptance("Admin - Watched Words", function (needs) {
     assert.equal(find(".modal-body li .tag").text(), "greeting");
   });
 });
+
+acceptance("Admin - Watched Words - Bad regular expressions", function (needs) {
+  needs.user();
+  needs.pretender((server, helper) => {
+    server.get("/admin/customize/watched_words.json", () => {
+      return helper.response({
+        actions: ["block", "censor", "require_approval", "flag", "replace"],
+        words: [
+          {
+            id: 1,
+            word: "[.*",
+            regexp: "[.*",
+            action: "block",
+          },
+        ],
+        regular_expressions: true,
+        compiled_regular_expressions: {
+          block: null,
+          censor: null,
+          require_approval: null,
+          flag: null,
+          replace: null,
+        },
+      });
+    });
+  });
+
+  test("shows an error message if regex is invalid", async function (assert) {
+    await visit("/admin/customize/watched_words/action/block");
+    assert.equal(find(".admin-watched-words .alert-error").length, 1);
+  });
+});
diff --git a/app/serializers/watched_word_serializer.rb b/app/serializers/watched_word_serializer.rb
index 6cc7972..4b3b138 100644
--- a/app/serializers/watched_word_serializer.rb
+++ b/app/serializers/watched_word_serializer.rb
@@ -7,10 +7,6 @@ class WatchedWordSerializer < ApplicationSerializer
     WordWatcher.word_to_regexp(word)
   end
 
-  def include_regexp?
-    WatchedWord.has_replacement?(action)
-  end
-
   def action
     WatchedWord.actions[object.action]
   end
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index aa28560..d097539 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -4701,6 +4701,7 @@ en:
         download: Download
         clear_all: Clear All
         clear_all_confirm: "Are you sure you want to clear all watched words for the %{action} action?"
+        invalid_regex: 'The watched word "%{word}" is an invalid regular expression.'
         actions:
           block: "Block"
           censor: "Censor"

GitHub sha: efd6394c

This commit appears in #13164 which was approved by ZogStriP. It was merged by nbianca.