Files
danbooru/test/unit/autocomplete_service_test.rb
evazion 2c1da660fd tags: allow tag abbreviations in searches and during tagging.
Expand the tag abbreviation system introduced in b0be8ae45 so that it
works in searches and when tagging posts, not just in autocomplete.

For example, you can tag a post with /evth and it will add the tag
eyebrows_visible_through_hair. You can search for /evth and it will
search for the tag eyebrows_visible_through_hair.

Some more examples:

* /ops is short for one-piece_swimsuit
* /hooe is short for hair_over_one_eye
* /saol is short for standing_on_one_leg
* /tlozbotw is short for the_legend_of_zelda:_breath_of_the_wild

If two tags have the same abbreviation, then the larger tag takes
precedence. For example, /be is short for blue_eyes, not brown_eyes,
because blue_eyes is the bigger tag.

If there is an existing shortcut alias that conflicts with the
abbreviation, then the alias take precedence. For example, /sh is short
for suzumiya_haruhi, not short_hair, because there's an old alias for
/sh -> suzumiya_haruhi.
2020-12-17 23:57:13 -06:00

191 lines
8.5 KiB
Ruby

require 'test_helper'
class AutocompleteServiceTest < ActiveSupport::TestCase
def autocomplete(query, type, **options)
results = AutocompleteService.new(query, type, **options).autocomplete_results
results.map { |r| r[:value] }
end
def assert_autocomplete_includes(expected_value, query, type, **options)
assert_includes(autocomplete(query, type, **options), expected_value)
end
def assert_autocomplete_equals(expected_value, query, type, **options)
assert_equal(expected_value, autocomplete(query, type, **options))
end
context "#autocomplete method" do
should "autocomplete artists" do
create(:artist, name: "bkub")
assert_autocomplete_includes("bkub", "bk", :artist)
end
should "autocomplete wiki pages" do
create(:wiki_page, title: "help:home")
assert_autocomplete_includes("help:home", "help", :wiki_page)
end
should "autocomplete users" do
@user = create(:user, name: "fumimi")
as(@user) do
assert_autocomplete_includes("fumimi", "fu", :user)
assert_autocomplete_includes("@fumimi", "fu", :mention)
assert_autocomplete_includes("user:fumimi", "user:fu", :tag_query)
end
end
should "autocomplete pools" do
as(create(:user)) do
create(:pool, name: "Disgustingly_Adorable")
end
assert_autocomplete_includes("Disgustingly_Adorable", "disgust", :pool)
assert_autocomplete_includes("pool:Disgustingly_Adorable", "pool:disgust", :tag_query)
assert_autocomplete_includes("pool:Disgustingly_Adorable", "-pool:disgust", :tag_query)
end
should "autocomplete favorite groups" do
user = create(:user)
create(:favorite_group, name: "Stuff", creator: user)
assert_autocomplete_equals(["Stuff"], "stu", :favorite_group, current_user: user)
assert_autocomplete_equals([], "stu", :favorite_group, current_user: User.anonymous)
assert_autocomplete_equals(["favgroup:Stuff"], "favgroup:stu", :tag_query, current_user: user)
assert_autocomplete_equals([], "favgroup:stu", :tag_query, current_user: User.anonymous)
end
should "autocomplete saved search labels" do
user = create(:user)
create(:saved_search, query: "bkub", labels: ["artists"], user: user)
assert_autocomplete_equals(["artists"], "art", :saved_search_label, current_user: user)
assert_autocomplete_equals([], "art", :saved_search_label, current_user: User.anonymous)
assert_autocomplete_equals(["search:artists"], "search:art", :tag_query, current_user: user)
assert_autocomplete_equals([], "search:art", :saved_search_label, current_user: User.anonymous)
end
should "autocomplete single tags" do
create(:tag, name: "touhou")
assert_autocomplete_includes("touhou", "tou", :tag)
end
context "for a tag search" do
should "autocomplete tags" do
create(:tag, name: "touhou")
assert_autocomplete_includes("touhou", "tou", :tag_query)
assert_autocomplete_includes("touhou", "TOU", :tag_query)
assert_autocomplete_includes("touhou", "-tou", :tag_query)
assert_autocomplete_includes("touhou", "~tou", :tag_query)
end
context "for a tag abbreviation" do
should "autocomplete abbreviations" do
create(:tag, name: "mole", post_count: 150)
create(:tag, name: "mole_under_eye", post_count: 100)
create(:tag, name: "mole_under_mouth", post_count: 50)
assert_autocomplete_equals(%w[mole mole_under_eye mole_under_mouth], "/m", :tag_query)
assert_autocomplete_equals(%w[mole_under_eye mole_under_mouth], "/mu", :tag_query)
assert_autocomplete_equals(%w[mole_under_mouth], "/mum", :tag_query)
assert_autocomplete_equals(%w[mole_under_eye], "/mue", :tag_query)
assert_autocomplete_equals(%w[mole_under_eye], "/*ue", :tag_query)
assert_autocomplete_includes("mole_under_eye", "-/mue", :tag_query)
assert_autocomplete_includes("mole_under_eye", "~/mue", :tag_query)
end
should "list aliases before abbreviations" do
create(:tag, name: "hair_ribbon", post_count: 300_000)
create(:tag, name: "hakurei_reimu", post_count: 50_000)
create(:tag_alias, antecedent_name: "/hr", consequent_name: "hakurei_reimu")
assert_autocomplete_equals(%w[hakurei_reimu hair_ribbon], "/hr", :tag_query)
end
end
should "autocomplete tags from wiki and artist other names" do
create(:tag, name: "touhou")
create(:tag, name: "bkub", category: Tag.categories.artist)
create(:wiki_page, title: "touhou", other_names: %w[東方 东方 동방])
create(:artist, name: "bkub", other_names: %w[大川ぶくぶ フミンバイン])
assert_autocomplete_equals(["touhou"], "", :tag_query)
assert_autocomplete_equals(["touhou"], "", :tag_query)
assert_autocomplete_equals(["touhou"], "", :tag_query)
assert_autocomplete_equals(["touhou"], "*東*", :tag_query)
assert_autocomplete_equals(["touhou"], "東*", :tag_query)
assert_autocomplete_equals([], "*東", :tag_query)
assert_autocomplete_equals(["touhou"], "*方*", :tag_query)
assert_autocomplete_equals(["touhou"], "*方", :tag_query)
assert_autocomplete_equals([], "", :tag_query)
assert_autocomplete_equals(["bkub"], "*大*", :tag_query)
assert_autocomplete_equals(["bkub"], "", :tag_query)
assert_autocomplete_equals([], "*大", :tag_query)
assert_autocomplete_equals(["bkub"], "*川*", :tag_query)
assert_autocomplete_equals([], "*川", :tag_query)
assert_autocomplete_equals([], "", :tag_query)
end
should "autocomplete wildcard searches" do
create(:tag, name: "mole", post_count: 150)
create(:tag, name: "mole_under_eye", post_count: 100)
create(:tag, name: "mole_under_mouth", post_count: 50)
assert_autocomplete_equals(%w[mole mole_under_eye mole_under_mouth], "mole*", :tag_query)
assert_autocomplete_equals(%w[mole_under_eye mole_under_mouth], "*under*", :tag_query)
assert_autocomplete_equals(%w[mole_under_eye], "*eye", :tag_query)
end
should "autocorrect misspelled tags" do
create(:tag, name: "touhou")
assert_autocomplete_equals(%w[touhou], "touhuo", :tag_query)
end
should "autocomplete static metatags" do
assert_autocomplete_equals(["status:active"], "status:act", :tag_query)
assert_autocomplete_equals(["parent:active"], "parent:act", :tag_query)
assert_autocomplete_equals(["child:active"], "child:act", :tag_query)
assert_autocomplete_equals(["rating:safe"], "rating:s", :tag_query)
assert_autocomplete_equals(["rating:questionable"], "rating:q", :tag_query)
assert_autocomplete_equals(["rating:explicit"], "rating:e", :tag_query)
assert_autocomplete_equals(["locked:rating"], "locked:r", :tag_query)
assert_autocomplete_equals(["locked:status"], "locked:s", :tag_query)
assert_autocomplete_equals(["locked:note"], "locked:n", :tag_query)
assert_autocomplete_equals(["embedded:true"], "embedded:t", :tag_query)
assert_autocomplete_equals(["embedded:false"], "embedded:f", :tag_query)
assert_autocomplete_equals(["filetype:jpg"], "filetype:j", :tag_query)
assert_autocomplete_equals(["filetype:png"], "filetype:p", :tag_query)
assert_autocomplete_equals(["filetype:gif"], "filetype:g", :tag_query)
assert_autocomplete_equals(["filetype:swf"], "filetype:s", :tag_query)
assert_autocomplete_equals(["filetype:zip"], "filetype:z", :tag_query)
assert_autocomplete_equals(["filetype:webm"], "filetype:w", :tag_query)
assert_autocomplete_equals(["filetype:mp4"], "filetype:m", :tag_query)
assert_autocomplete_equals(["commentary:true"], "commentary:tru", :tag_query)
assert_autocomplete_equals(["commentary:false"], "commentary:fal", :tag_query)
assert_autocomplete_equals(["commentary:translated"], "commentary:trans", :tag_query)
assert_autocomplete_equals(["commentary:untranslated"], "commentary:untrans", :tag_query)
assert_autocomplete_equals(["disapproved:breaks_rules"], "disapproved:break", :tag_query)
assert_autocomplete_equals(["disapproved:poor_quality"], "disapproved:poor", :tag_query)
assert_autocomplete_equals(["disapproved:disinterest"], "disapproved:dis", :tag_query)
assert_autocomplete_equals(["order:score", "order:score_asc"], "order:sco", :tag_query)
end
end
end
end