mirror of
https://github.com/discourse/discourse.git
synced 2025-04-28 14:14:35 +08:00

This feature allows @ mentions to prioritize showing members of a group who have explicit permission to a category. This makes it far easier to @ mention group member when composing topics in categories where only the group has access. For example: If Sam, Jane an Joan have access to bugs category. Then `@` will auto complete to (jane,joan,sam) ordered on last seen at This feature works on new topics and existing topics. There is an explicit exclusion of trust level 0,1,2 groups cause they get too big.
202 lines
6.4 KiB
Ruby
202 lines
6.4 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'rails_helper'
|
|
|
|
describe UserSearch do
|
|
|
|
let(:topic) { Fabricate :topic }
|
|
let(:topic2) { Fabricate :topic }
|
|
let(:topic3) { Fabricate :topic }
|
|
let(:topic4) { Fabricate :topic }
|
|
let(:user1) { Fabricate :user, username: "mrb", name: "Michael Madsen", last_seen_at: 10.days.ago }
|
|
let(:user2) { Fabricate :user, username: "mrblue", name: "Eddie Code", last_seen_at: 9.days.ago }
|
|
let(:user3) { Fabricate :user, username: "mrorange", name: "Tim Roth", last_seen_at: 8.days.ago }
|
|
let(:user4) { Fabricate :user, username: "mrpink", name: "Steve Buscemi", last_seen_at: 7.days.ago }
|
|
let(:user5) { Fabricate :user, username: "mrbrown", name: "Quentin Tarantino", last_seen_at: 6.days.ago }
|
|
let(:user6) { Fabricate :user, username: "mrwhite", name: "Harvey Keitel", last_seen_at: 5.days.ago }
|
|
let!(:inactive) { Fabricate :user, username: "Ghost", active: false }
|
|
let(:admin) { Fabricate :admin, username: "theadmin" }
|
|
let(:moderator) { Fabricate :moderator, username: "themod" }
|
|
let(:staged) { Fabricate :staged }
|
|
|
|
before do
|
|
SearchIndexer.enable
|
|
end
|
|
|
|
def search_for(*args)
|
|
UserSearch.new(*args).search
|
|
end
|
|
|
|
it 'finds users in secure category' do
|
|
group = Fabricate(:group)
|
|
user = Fabricate(:user)
|
|
group.add(user)
|
|
group.save
|
|
|
|
category = Fabricate.build(
|
|
:category,
|
|
read_restricted: true,
|
|
user: user
|
|
)
|
|
# TODO: maybe we amend all category fabrication to skip this?
|
|
# test is half a second faster
|
|
category.skip_category_definition = true
|
|
category.save!
|
|
|
|
Fabricate(:category_group, category: category, group: group)
|
|
|
|
results = search_for("", category_id: category.id)
|
|
|
|
expect(user.username).to eq(results[0].username)
|
|
expect(results.length).to eq(1)
|
|
|
|
topic = Fabricate(:topic, category: category)
|
|
_post = Fabricate(:post, user: topic.user, topic: topic)
|
|
|
|
results = search_for("", topic_id: topic.id)
|
|
|
|
expect(results.length).to eq(2)
|
|
|
|
expect(results.map(&:username)).to contain_exactly(
|
|
user.username, topic.user.username
|
|
)
|
|
end
|
|
|
|
it 'allows for correct underscore searching' do
|
|
Fabricate(:user, username: 'Under_Score')
|
|
Fabricate(:user, username: 'undertaker')
|
|
|
|
expect(search_for("under_sc").length).to eq(1)
|
|
expect(search_for("under_").length).to eq(1)
|
|
end
|
|
|
|
it 'allows filtering by group' do
|
|
group = Fabricate(:group)
|
|
sam = Fabricate(:user, username: 'sam')
|
|
_samantha = Fabricate(:user, username: 'samantha')
|
|
group.add(sam)
|
|
|
|
results = search_for("sam", groups: [group])
|
|
expect(results.count).to eq(1)
|
|
end
|
|
|
|
it 'allows filtering by multiple groups' do
|
|
group_1 = Fabricate(:group)
|
|
sam = Fabricate(:user, username: 'sam')
|
|
group_2 = Fabricate(:group)
|
|
samantha = Fabricate(:user, username: 'samantha')
|
|
group_1.add(sam)
|
|
group_2.add(samantha)
|
|
|
|
results = search_for("sam", groups: [group_1, group_2])
|
|
expect(results.count).to eq(2)
|
|
end
|
|
|
|
context "with seed data" do
|
|
|
|
before do
|
|
|
|
Fabricate :post, user: user1, topic: topic
|
|
Fabricate :post, user: user2, topic: topic2
|
|
Fabricate :post, user: user3, topic: topic
|
|
Fabricate :post, user: user4, topic: topic
|
|
Fabricate :post, user: user5, topic: topic3
|
|
Fabricate :post, user: user6, topic: topic
|
|
Fabricate :post, user: staged, topic: topic4
|
|
|
|
user6.update(suspended_at: 1.day.ago, suspended_till: 1.year.from_now)
|
|
end
|
|
|
|
# this is a seriously expensive integration test,
|
|
# re-creating this entire test db is too expensive reuse
|
|
it "operates correctly" do
|
|
# normal search
|
|
results = search_for(user1.name.split(" ").first)
|
|
expect(results.size).to eq(1)
|
|
expect(results.first.username).to eq(user1.username)
|
|
|
|
# lower case
|
|
results = search_for(user1.name.split(" ").first.downcase)
|
|
expect(results.size).to eq(1)
|
|
expect(results.first).to eq(user1)
|
|
|
|
# username
|
|
results = search_for(user4.username)
|
|
expect(results.size).to eq(1)
|
|
expect(results.first).to eq(user4)
|
|
|
|
# case insensitive
|
|
results = search_for(user4.username.upcase)
|
|
expect(results.size).to eq(1)
|
|
expect(results.first).to eq(user4)
|
|
|
|
# substrings
|
|
# only staff members see suspended users in results
|
|
results = search_for("mr")
|
|
expect(results.size).to eq(5)
|
|
expect(results).not_to include(user6)
|
|
expect(search_for("mr", searching_user: user1).size).to eq(5)
|
|
|
|
results = search_for("mr", searching_user: admin)
|
|
expect(results.size).to eq(6)
|
|
expect(results).to include(user6)
|
|
expect(search_for("mr", searching_user: moderator).size).to eq(6)
|
|
|
|
results = search_for(user1.username, searching_user: admin)
|
|
expect(results.size).to eq(3)
|
|
|
|
results = search_for("MR", searching_user: admin)
|
|
expect(results.size).to eq(6)
|
|
|
|
results = search_for("MRB", searching_user: admin, limit: 2)
|
|
expect(results.size).to eq(2)
|
|
|
|
# topic priority
|
|
results = search_for(user1.username, topic_id: topic.id)
|
|
expect(results.first).to eq(user1)
|
|
|
|
results = search_for(user1.username, topic_id: topic2.id)
|
|
expect(results[1]).to eq(user2)
|
|
|
|
results = search_for(user1.username, topic_id: topic3.id)
|
|
expect(results[1]).to eq(user5)
|
|
|
|
# When searching by name is enabled, it returns the record
|
|
SiteSetting.enable_names = true
|
|
results = search_for("Tarantino")
|
|
expect(results.size).to eq(1)
|
|
|
|
results = search_for("coding")
|
|
expect(results.size).to eq(0)
|
|
|
|
results = search_for("z")
|
|
expect(results.size).to eq(0)
|
|
|
|
# When searching by name is disabled, it will not return the record
|
|
SiteSetting.enable_names = false
|
|
results = search_for("Tarantino")
|
|
expect(results.size).to eq(0)
|
|
|
|
# find an exact match first
|
|
results = search_for("mrB")
|
|
expect(results.first.username).to eq(user1.username)
|
|
|
|
# don't return inactive users
|
|
results = search_for(inactive.username)
|
|
expect(results).to be_blank
|
|
|
|
# don't return staged users
|
|
results = search_for(staged.username)
|
|
expect(results).to be_blank
|
|
|
|
results = search_for(staged.username, include_staged_users: true)
|
|
expect(results.first.username).to eq(staged.username)
|
|
|
|
results = search_for("", topic_id: topic.id, searching_user: user1)
|
|
|
|
# mrb is omitted, mrb is current user
|
|
expect(results.map(&:username)).to eq(["mrpink", "mrorange"])
|
|
end
|
|
end
|
|
end
|