diff --git a/app/javascript/src/javascripts/autocomplete.js.erb b/app/javascript/src/javascripts/autocomplete.js.erb index 4899141c1..05361d383 100644 --- a/app/javascript/src/javascripts/autocomplete.js.erb +++ b/app/javascript/src/javascripts/autocomplete.js.erb @@ -10,8 +10,8 @@ Autocomplete.ORDER_METATAGS = <%= Tag::ORDER_METATAGS.to_json.html_safe %>; /* eslint-enable */ Autocomplete.TAG_PREFIXES = "-|~|" + Object.keys(Autocomplete.TAG_CATEGORIES).map(category => category + ":").join("|"); -Autocomplete.TAG_PREFIXES_REGEX = new RegExp("^(" + Autocomplete.TAG_PREFIXES + ")(.*)$", "i"); -Autocomplete.METATAGS_REGEX = new RegExp("^(" + Autocomplete.METATAGS.join("|") + "):(.*)$", "i"); +Autocomplete.METATAGS_REGEX = Autocomplete.METATAGS.concat(Object.keys(Autocomplete.TAG_CATEGORIES)).join("|"); +Autocomplete.TERM_REGEX = new RegExp(`([-~]*)(?:(${Autocomplete.METATAGS_REGEX}):)?(\\S*)$`, "i"); Autocomplete.initialize_all = function() { if (Utility.meta("enable-auto-complete") === "true") { @@ -271,34 +271,14 @@ Autocomplete.normal_source = function(term, resp) { } Autocomplete.parse_query = function(text, caret) { - var operator = ""; - var metatag = ""; - var term = ""; + let before_caret_text = text.substring(0, caret); + let match = before_caret_text.match(Autocomplete.TERM_REGEX); - var before_caret_text = text.substring(0, caret); - var match = before_caret_text.match(/\S+$/g); - if (match) { - term = match[0]; - } else { - return {}; - } + let operator = match[1]; + let metatag = match[2] ? match[2].toLowerCase() : "tag"; + let term = match[3]; - match = term.match(/^([-~])(.*)$/); - if (match) { - operator = match[1]; - term = match[2]; - } - - match = term.match(Autocomplete.TAG_PREFIXES_REGEX); - if (match) { - term = match[2]; - } - - match = term.match(Autocomplete.METATAGS_REGEX); - if (match) { - metatag = match[1].toLowerCase(); - term = match[2]; - } else { + if (metatag in Autocomplete.TAG_CATEGORIES) { metatag = "tag"; } diff --git a/test/application_system_test_case.rb b/test/application_system_test_case.rb index 6faf93767..9ca42980a 100644 --- a/test/application_system_test_case.rb +++ b/test/application_system_test_case.rb @@ -2,5 +2,5 @@ require "test_helper" class ApplicationSystemTestCase < ActionDispatch::SystemTestCase include SystemTestHelper - driven_by :selenium, using: :firefox, screen_size: [1400, 1400] + driven_by :selenium, using: :headless_firefox, screen_size: [1400, 1400] end diff --git a/test/system/autocomplete_test.rb b/test/system/autocomplete_test.rb index 4326a1176..6877b33e9 100644 --- a/test/system/autocomplete_test.rb +++ b/test/system/autocomplete_test.rb @@ -30,6 +30,12 @@ class AutocompleteTest < ApplicationSystemTestCase assert_autocomplete_equals(values, text, id: "forum_post_body") end + def assert_inserted_completion(result, query, id: "tags") + autocomplete(id, query) + first("ul.ui-autocomplete li").click + assert_equal(result, find_field(id: id).value) + end + context "Autocomplete" do context "for post searches" do should "work for static metatags" do @@ -85,8 +91,6 @@ class AutocompleteTest < ApplicationSystemTestCase assert_search_autocomplete_equals(["bkub"], "char:bkub") assert_search_autocomplete_equals(["bkub"], "gen:bkub") assert_search_autocomplete_equals(["bkub"], "meta:bkub") - assert_search_autocomplete_equals(["bkub"], "-char:bkub") - assert_search_autocomplete_equals(["bkub"], "~char:bkub") assert_search_autocomplete_equals(["bkub"], "b*") assert_search_autocomplete_equals(["bkub"], "B*") @@ -98,16 +102,38 @@ class AutocompleteTest < ApplicationSystemTestCase assert_search_autocomplete_equals([], "one two") end + should "correct invalid operator combinations" do + create(:tag, name: "bkub", post_count: 42) + + assert_search_autocomplete_equals(["bkub"], "foo ---bkub") + assert_search_autocomplete_equals(["bkub"], "foo ~~~bkub") + + assert_search_autocomplete_equals(["rating:safe"], "--rating:s") + assert_search_autocomplete_equals(["rating:safe"], "-~rating:s") + assert_search_autocomplete_equals(["rating:safe"], "~-rating:s") + assert_search_autocomplete_equals(["rating:safe"], "~~rating:s") + assert_search_autocomplete_equals(["rating:safe"], "---rating:s") + assert_search_autocomplete_equals(["rating:safe"], "~~~rating:s") + end + + should "ignore invalid prefix + metatag combinations" do + assert_search_autocomplete_equals([], "char:rating:s") + end + should "insert completions on click" do visit posts_path - autocomplete("tags", "rating:s") - first("ul.ui-autocomplete li").click - assert_equal("rating:safe ", find_field(id: "tags").value) + create(:tag, name: "bkub", post_count: 42) + assert_inserted_completion("bkub ", "b") + assert_inserted_completion("-bkub ", "-b") + assert_inserted_completion("~bkub ", "~b") + assert_inserted_completion("tag bkub ", "tag b") + assert_inserted_completion("tag char:bkub ", "tag char:b") - autocomplete("tags", "one two rating:s") - first("ul.ui-autocomplete li").click - assert_equal("one two rating:safe ", find_field(id: "tags").value) + assert_inserted_completion("rating:safe ", "rating:s") + assert_inserted_completion("-rating:safe ", "-rating:s") + assert_inserted_completion("-rating:safe ", "---rating:s") + assert_inserted_completion("tag rating:safe ", "tag rating:s") end end