diff --git a/app/components/autocomplete_component.rb b/app/components/autocomplete_component.rb index e7a75f665..d18b42864 100644 --- a/app/components/autocomplete_component.rb +++ b/app/components/autocomplete_component.rb @@ -56,7 +56,7 @@ class AutocompleteComponent < ApplicationComponent # highlight_matching_words("very_long_hair", "long_ha*") => "very_long_hair" def highlight_matching_words(target, 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.map do |word| diff --git a/test/functional/autocomplete_controller_test.rb b/test/functional/autocomplete_controller_test.rb index 5acb481af..6c7a58cca 100644 --- a/test/functional/autocomplete_controller_test.rb +++ b/test/functional/autocomplete_controller_test.rb @@ -12,6 +12,17 @@ class AutocompleteControllerTest < ActionDispatch::IntegrationTest assert_equal(expected_value, autocomplete(query, type)) 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>/) { $1.upcase } + end + + assert_equal(results, expected_results) + end + context "Autocomplete controller" do context "index action" do should "work for opensearch queries" do @@ -34,6 +45,8 @@ class AutocompleteControllerTest < ActionDispatch::IntegrationTest end 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: "long_hair", post_count: 10_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: "open_mouth") 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: "oc", consequent_name: "original") 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[crying_with_eyes_open], "open_eyes") assert_autocomplete_equals(%w[open_mouth], "mouth_open") assert_autocomplete_equals(%w[black_hair], "dark") - end - - 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(%w[original], "oc") assert_autocomplete_equals(["user:foobar"], "user:foo") + assert_autocomplete_equals(["pool:foobar"], "pool:foo") end - should "work for the pool: metatag" do - as(create(:user)) { create(:pool, name: "foobar") } + should "highlight matches correctly" do + 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 should "work for a missing type" do