autocomplete: fix incorrect highlighting when tag contains repeated words.
Fix tags like `short_shorts` or `hunter_x_hunter` being highlighted incorrectly. Typing `short_sh` would highlight it as SHort_SHorts instead of as SHORT_SHorts.
This commit is contained in:
@@ -56,7 +56,7 @@ class AutocompleteComponent < ApplicationComponent
|
|||||||
# highlight_matching_words("very_long_hair", "long_ha*") => "<span>very_</span><b>long</b><span>_</span><b>hair</b>"
|
# highlight_matching_words("very_long_hair", "long_ha*") => "<span>very_</span><b>long</b><span>_</span><b>hair</b>"
|
||||||
def highlight_matching_words(target, pattern)
|
def highlight_matching_words(target, pattern)
|
||||||
pattern_words = Tag.parse_query(pattern)
|
pattern_words = Tag.parse_query(pattern)
|
||||||
pattern_words.sort_by! { |word| [word.include?("*") ? 0 : 1, -word.size] }
|
pattern_words.sort_by! { |word| [word.include?("*") ? 1 : 0, -word.size] }
|
||||||
|
|
||||||
target_words = Tag.split_words(target)
|
target_words = Tag.split_words(target)
|
||||||
target_words.map do |word|
|
target_words.map do |word|
|
||||||
|
|||||||
@@ -12,6 +12,17 @@ class AutocompleteControllerTest < ActionDispatch::IntegrationTest
|
|||||||
assert_equal(expected_value, autocomplete(query, type))
|
assert_equal(expected_value, autocomplete(query, type))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def assert_autocomplete_highlights(expected_results, query, type = "tag_query")
|
||||||
|
get autocomplete_index_path(search: { query: query, type: type })
|
||||||
|
assert_response :success
|
||||||
|
|
||||||
|
results = response.parsed_body.css("li a").map do |html|
|
||||||
|
html.inner_html.strip.remove(/<\/?span>/).gsub(/<b>(.*?)<\/b>/) { $1.upcase }
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal(results, expected_results)
|
||||||
|
end
|
||||||
|
|
||||||
context "Autocomplete controller" do
|
context "Autocomplete controller" do
|
||||||
context "index action" do
|
context "index action" do
|
||||||
should "work for opensearch queries" do
|
should "work for opensearch queries" do
|
||||||
@@ -34,6 +45,8 @@ class AutocompleteControllerTest < ActionDispatch::IntegrationTest
|
|||||||
end
|
end
|
||||||
|
|
||||||
should "match tags containing the given words" do
|
should "match tags containing the given words" do
|
||||||
|
create(:user, name: "foobar")
|
||||||
|
as(create(:user)) { create(:pool, name: "foobar") }
|
||||||
create(:tag, name: "short_hair", post_count: 15_000)
|
create(:tag, name: "short_hair", post_count: 15_000)
|
||||||
create(:tag, name: "long_hair", post_count: 10_000)
|
create(:tag, name: "long_hair", post_count: 10_000)
|
||||||
create(:tag, name: "very_long_hair", post_count: 5_000)
|
create(:tag, name: "very_long_hair", post_count: 5_000)
|
||||||
@@ -42,32 +55,51 @@ class AutocompleteControllerTest < ActionDispatch::IntegrationTest
|
|||||||
create(:tag, name: "crying_with_eyes_open")
|
create(:tag, name: "crying_with_eyes_open")
|
||||||
create(:tag, name: "open_mouth")
|
create(:tag, name: "open_mouth")
|
||||||
create(:tag, name: "black_hair")
|
create(:tag, name: "black_hair")
|
||||||
|
create(:tag, name: "original")
|
||||||
create(:tag_alias, antecedent_name: "dark_hair", consequent_name: "black_hair")
|
create(:tag_alias, antecedent_name: "dark_hair", consequent_name: "black_hair")
|
||||||
|
create(:tag_alias, antecedent_name: "oc", consequent_name: "original")
|
||||||
|
|
||||||
assert_autocomplete_equals(%w[long_hair very_long_hair absurdly_long_hair], "long_hair")
|
assert_autocomplete_equals(%w[long_hair very_long_hair absurdly_long_hair], "long_hair")
|
||||||
assert_autocomplete_equals(%w[souryuu_asuka_langley], "asuka")
|
assert_autocomplete_equals(%w[souryuu_asuka_langley], "asuka")
|
||||||
assert_autocomplete_equals(%w[crying_with_eyes_open], "open_eyes")
|
assert_autocomplete_equals(%w[crying_with_eyes_open], "open_eyes")
|
||||||
assert_autocomplete_equals(%w[open_mouth], "mouth_open")
|
assert_autocomplete_equals(%w[open_mouth], "mouth_open")
|
||||||
assert_autocomplete_equals(%w[black_hair], "dark")
|
assert_autocomplete_equals(%w[black_hair], "dark")
|
||||||
end
|
assert_autocomplete_equals(%w[original], "oc")
|
||||||
|
|
||||||
should "work for an aliased tag" do
|
|
||||||
create(:tag, name: "original")
|
|
||||||
create(:tag_alias, antecedent_name: "oc", consequent_name: "original")
|
|
||||||
|
|
||||||
assert_autocomplete_equals(["original"], "oc")
|
|
||||||
end
|
|
||||||
|
|
||||||
should "work for the user: metatag" do
|
|
||||||
create(:user, name: "foobar")
|
|
||||||
|
|
||||||
assert_autocomplete_equals(["user:foobar"], "user:foo")
|
assert_autocomplete_equals(["user:foobar"], "user:foo")
|
||||||
|
assert_autocomplete_equals(["pool:foobar"], "pool:foo")
|
||||||
end
|
end
|
||||||
|
|
||||||
should "work for the pool: metatag" do
|
should "highlight matches correctly" do
|
||||||
as(create(:user)) { create(:pool, name: "foobar") }
|
create(:tag, name: "short_hair")
|
||||||
|
create(:tag, name: "very_long_hair")
|
||||||
|
create(:tag, name: "short_shorts")
|
||||||
|
create(:tag, name: "sleeves_rolled_up")
|
||||||
|
create(:tag, name: "jack-o'-lantern")
|
||||||
|
create(:tag, name: %q{don't_say_"lazy"})
|
||||||
|
|
||||||
assert_autocomplete_equals(["pool:foobar"], "pool:foo")
|
assert_autocomplete_highlights([%q{don't say "LAZY"}], "lazy")
|
||||||
|
|
||||||
|
assert_autocomplete_highlights(["VERY long hair"], "very")
|
||||||
|
assert_autocomplete_highlights(["very LONG hair"], "long")
|
||||||
|
assert_autocomplete_highlights(["short HAIR", "very long HAIR"], "hair")
|
||||||
|
|
||||||
|
assert_autocomplete_highlights(["SLEEVES ROLLED UP"], "sleeves_rolled_up")
|
||||||
|
assert_autocomplete_highlights(["SLEEVES ROLLED UP"], "rolled-up_sleeves")
|
||||||
|
|
||||||
|
assert_autocomplete_highlights(["JACK-O'-LANTERN"], "jack-o'-lantern")
|
||||||
|
assert_autocomplete_highlights(["JACK-O'-LANTERN"], "jack_o'_lantern")
|
||||||
|
assert_autocomplete_highlights(["JACK-O'-LANTERN"], "jack_o_lantern")
|
||||||
|
|
||||||
|
assert_autocomplete_highlights(["SHORT hair", "SHORT SHORTs"], "short")
|
||||||
|
assert_autocomplete_highlights(["SHORT SHOrts", "SHORT hair"], "short_sho")
|
||||||
|
|
||||||
|
assert_autocomplete_highlights(["VERY long hair"], "very*")
|
||||||
|
assert_autocomplete_highlights(["very LONG hair"], "*long*")
|
||||||
|
assert_autocomplete_highlights(["short HAIR", "very long HAIR"], "*hair")
|
||||||
|
assert_autocomplete_highlights(["VEry LOng HAir"], "*ve*lo*ha*")
|
||||||
|
assert_autocomplete_highlights(["vERy lONg hAIr"], "*er*on*ai*")
|
||||||
|
assert_autocomplete_highlights(["veRY loNG haIR"], "*ry*ng*ir*")
|
||||||
end
|
end
|
||||||
|
|
||||||
should "work for a missing type" do
|
should "work for a missing type" do
|
||||||
|
|||||||
Reference in New Issue
Block a user