From f421d9bdd6a85d6df907848d8ad35c758ef636ac Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9gis=20Hanol?= <regis@hanol.fr>
Date: Mon, 25 Jan 2021 21:27:15 +0100
Subject: [PATCH] FIX: only de-prioritise exact matches in mentions (#11843)

Not when doing a site-wide search like we do in the Directory.

This solves the following specfailure:

  1) DirectoryItemsController with data finds user by name
     Failure/Error: expect(json['directory_items'].length).to eq(1)

       expected: 1
            got: 0

       (compared using ==)
     # ./spec/requests/directory_items_controller_spec.rb:88:in `block (3 levels) in <main>'
     # ./spec/rails_helper.rb:271:in `block (2 levels) in <top (required)>'
     # ./bundle/ruby/2.7.0/gems/webmock-3.11.1/lib/webmock/rspec.rb:37:in `block (2 levels) in <top (required)>'
---
 app/models/user_search.rb       | 11 +++++++----
 spec/models/user_search_spec.rb |  4 ++--
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/app/models/user_search.rb b/app/models/user_search.rb
index aafc0d3e812..7498b230beb 100644
--- a/app/models/user_search.rb
+++ b/app/models/user_search.rb
@@ -64,11 +64,14 @@ class UserSearch
   def search_ids
     users = Set.new
 
-    # 1. exact username matches active in the past year
+    # 1. exact username matches
     if @term.present?
-      scoped_users
-        .where(username_lower: @term)
-        .where('last_seen_at > ?', 1.year.ago)
+      exact_matches = scoped_users.where(username_lower: @term)
+
+      # don't polute mentions with users who haven't shown up in over a year
+      exact_matches = exact_matches.where('last_seen_at > ?', 1.year.ago) if @topic_id || @category_id
+
+      exact_matches
         .limit(@limit)
         .pluck(:id)
         .each { |id| users << id }
diff --git a/spec/models/user_search_spec.rb b/spec/models/user_search_spec.rb
index d631d59d972..c72abc84686 100644
--- a/spec/models/user_search_spec.rb
+++ b/spec/models/user_search_spec.rb
@@ -212,13 +212,13 @@ describe UserSearch do
       expect(results).to eq [mr_b, mr_brown, mr_blue].map(&:username)
     end
 
-    it "doesn't prioritises exact matches for users who haven't been seen in more than 1 year" do
+    it "doesn't prioritises exact matches mentions for users who haven't been seen in over a year" do
       abcdef = Fabricate(:user, username: "abcdef", last_seen_at: 2.days.ago)
       abcde  = Fabricate(:user, username: "abcde", last_seen_at: 2.weeks.ago)
       abcd   = Fabricate(:user, username: "abcd", last_seen_at: 2.months.ago)
       abc    = Fabricate(:user, username: "abc", last_seen_at: 2.years.ago)
 
-      results = search_for("abc")
+      results = search_for("abc", topic_id: topic.id)
       expect(results).to eq [abcdef, abcde, abcd, abc].map(&:username)
     end