2013-02-28 14:52:35 -05:00
|
|
|
|
# encoding: utf-8
|
|
|
|
|
|
2015-10-11 05:41:23 -04:00
|
|
|
|
require 'rails_helper'
|
2013-08-01 20:31:36 -04:00
|
|
|
|
require_dependency 'search'
|
2013-02-05 14:16:51 -05:00
|
|
|
|
|
|
|
|
|
describe Search do
|
|
|
|
|
|
2013-05-13 21:59:55 -04:00
|
|
|
|
before do
|
2016-12-21 21:13:14 -05:00
|
|
|
|
SearchIndexer.enable
|
2013-05-13 21:59:55 -04:00
|
|
|
|
end
|
|
|
|
|
|
2013-02-25 11:42:20 -05:00
|
|
|
|
context 'post indexing observer' do
|
|
|
|
|
before do
|
2013-02-05 14:16:51 -05:00
|
|
|
|
@category = Fabricate(:category, name: 'america')
|
2013-03-11 09:51:24 -04:00
|
|
|
|
@topic = Fabricate(:topic, title: 'sam saffron test topic', category: @category)
|
2013-02-05 14:16:51 -05:00
|
|
|
|
@post = Fabricate(:post, topic: @topic, raw: 'this <b>fun test</b> <img src="bla" title="my image">')
|
2013-05-22 15:33:33 -04:00
|
|
|
|
@indexed = @post.post_search_data.search_data
|
2013-02-05 14:16:51 -05:00
|
|
|
|
end
|
2014-09-01 03:04:40 -04:00
|
|
|
|
|
|
|
|
|
it "should index correctly" do
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(@indexed).to match(/fun/)
|
|
|
|
|
expect(@indexed).to match(/sam/)
|
|
|
|
|
expect(@indexed).to match(/america/)
|
2013-02-05 14:16:51 -05:00
|
|
|
|
|
2013-02-06 20:09:31 -05:00
|
|
|
|
@topic.title = "harpi is the new title"
|
2013-02-05 14:16:51 -05:00
|
|
|
|
@topic.save!
|
2013-05-22 15:33:33 -04:00
|
|
|
|
@post.post_search_data.reload
|
|
|
|
|
|
|
|
|
|
@indexed = @post.post_search_data.search_data
|
2013-02-05 14:16:51 -05:00
|
|
|
|
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(@indexed).to match(/harpi/)
|
2013-02-05 14:16:51 -05:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2013-02-25 11:42:20 -05:00
|
|
|
|
context 'user indexing observer' do
|
|
|
|
|
before do
|
2013-02-05 14:16:51 -05:00
|
|
|
|
@user = Fabricate(:user, username: 'fred', name: 'bob jones')
|
2013-05-22 15:33:33 -04:00
|
|
|
|
@indexed = @user.user_search_data.search_data
|
2013-02-05 14:16:51 -05:00
|
|
|
|
end
|
|
|
|
|
|
2014-09-02 05:15:08 -04:00
|
|
|
|
it "should pick up on data" do
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(@indexed).to match(/fred/)
|
|
|
|
|
expect(@indexed).to match(/jone/)
|
2013-02-05 14:16:51 -05:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2013-02-25 11:42:20 -05:00
|
|
|
|
context 'category indexing observer' do
|
|
|
|
|
before do
|
2013-02-05 14:16:51 -05:00
|
|
|
|
@category = Fabricate(:category, name: 'america')
|
2013-05-22 15:33:33 -04:00
|
|
|
|
@indexed = @category.category_search_data.search_data
|
2013-02-05 14:16:51 -05:00
|
|
|
|
end
|
|
|
|
|
|
2013-02-25 11:42:20 -05:00
|
|
|
|
it "should pick up on name" do
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(@indexed).to match(/america/)
|
2013-02-05 14:16:51 -05:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
2017-06-07 02:23:48 -04:00
|
|
|
|
it 'strips zero-width characters from search terms' do
|
|
|
|
|
term = "\u0063\u0061\u0070\u0079\u200b\u200c\u200d\ufeff\u0062\u0061\u0072\u0061".encode("UTF-8")
|
|
|
|
|
|
|
|
|
|
expect(term == 'capybara').to eq(false)
|
|
|
|
|
|
2017-06-21 15:51:15 -04:00
|
|
|
|
search = Search.new(term)
|
2017-06-07 02:23:48 -04:00
|
|
|
|
expect(search.valid?).to eq(true)
|
|
|
|
|
expect(search.term).to eq('capybara')
|
2017-06-21 15:51:15 -04:00
|
|
|
|
expect(search.clean_term).to eq('capybara')
|
2017-06-07 02:23:48 -04:00
|
|
|
|
end
|
|
|
|
|
|
2017-12-12 00:47:28 -05:00
|
|
|
|
it 'replaces curly quotes to regular quotes in search terms' do
|
|
|
|
|
term = '“discourse”'
|
|
|
|
|
|
|
|
|
|
expect(term == '"discourse"').to eq(false)
|
|
|
|
|
|
|
|
|
|
search = Search.new(term)
|
|
|
|
|
expect(search.valid?).to eq(true)
|
|
|
|
|
expect(search.term).to eq('"discourse"')
|
|
|
|
|
expect(search.clean_term).to eq('"discourse"')
|
|
|
|
|
end
|
|
|
|
|
|
2013-03-07 10:52:01 -05:00
|
|
|
|
it 'does not search when the search term is too small' do
|
2016-08-09 14:48:39 -04:00
|
|
|
|
search = Search.new('evil', min_search_term_length: 5)
|
|
|
|
|
search.execute
|
|
|
|
|
expect(search.valid?).to eq(false)
|
|
|
|
|
expect(search.term).to eq('')
|
|
|
|
|
end
|
|
|
|
|
|
2016-08-11 11:52:53 -04:00
|
|
|
|
it 'needs at least one term that hits the length' do
|
2016-08-09 14:48:39 -04:00
|
|
|
|
search = Search.new('a b c d', min_search_term_length: 5)
|
|
|
|
|
search.execute
|
|
|
|
|
expect(search.valid?).to eq(false)
|
|
|
|
|
expect(search.term).to eq('')
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'searches for quoted short terms' do
|
|
|
|
|
search = Search.new('"a b c d"', min_search_term_length: 5)
|
|
|
|
|
search.execute
|
|
|
|
|
expect(search.valid?).to eq(true)
|
|
|
|
|
expect(search.term).to eq('"a b c d"')
|
|
|
|
|
end
|
|
|
|
|
|
2016-08-11 11:52:53 -04:00
|
|
|
|
it 'searches for short terms if one hits the length' do
|
2016-08-09 14:48:39 -04:00
|
|
|
|
search = Search.new('a b c okaylength', min_search_term_length: 5)
|
|
|
|
|
search.execute
|
|
|
|
|
expect(search.valid?).to eq(true)
|
2016-08-11 11:52:53 -04:00
|
|
|
|
expect(search.term).to eq('a b c okaylength')
|
2013-03-07 10:52:01 -05:00
|
|
|
|
end
|
|
|
|
|
|
2013-02-05 14:16:51 -05:00
|
|
|
|
it 'escapes non alphanumeric characters' do
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(Search.execute('foo :!$);}]>@\#\"\'').posts.length).to eq(0) # There are at least three levels of sanitation for Search.query!
|
2013-08-26 16:25:02 -04:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it "doesn't raise an error when single quotes are present" do
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(Search.execute("'hello' world").posts.length).to eq(0) # There are at least three levels of sanitation for Search.query!
|
2013-02-05 14:16:51 -05:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'works when given two terms with spaces' do
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect { Search.execute('evil trout') }.not_to raise_error
|
2013-02-05 14:16:51 -05:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'users' do
|
|
|
|
|
let!(:user) { Fabricate(:user) }
|
2014-09-02 05:15:08 -04:00
|
|
|
|
let(:result) { Search.execute('bruce', type_filter: 'user') }
|
2013-02-05 14:16:51 -05:00
|
|
|
|
|
|
|
|
|
it 'returns a result' do
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(result.users.length).to eq(1)
|
|
|
|
|
expect(result.users[0].id).to eq(user.id)
|
2013-02-05 14:16:51 -05:00
|
|
|
|
end
|
2015-10-28 14:56:08 -04:00
|
|
|
|
|
|
|
|
|
context 'hiding user profiles' do
|
2017-07-07 02:09:14 -04:00
|
|
|
|
before { SiteSetting.hide_user_profiles_from_public = true }
|
2015-10-28 14:56:08 -04:00
|
|
|
|
|
|
|
|
|
it 'returns no result for anon' do
|
|
|
|
|
expect(result.users.length).to eq(0)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'returns a result for logged in users' do
|
|
|
|
|
result = Search.execute('bruce', type_filter: 'user', guardian: Guardian.new(user))
|
|
|
|
|
expect(result.users.length).to eq(1)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
2013-02-05 14:16:51 -05:00
|
|
|
|
end
|
|
|
|
|
|
2014-10-24 19:20:41 -04:00
|
|
|
|
context 'inactive users' do
|
|
|
|
|
let!(:inactive_user) { Fabricate(:inactive_user, active: false) }
|
|
|
|
|
let(:result) { Search.execute('bruce') }
|
|
|
|
|
|
|
|
|
|
it 'does not return a result' do
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(result.users.length).to eq(0)
|
2014-10-24 19:20:41 -04:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2015-11-18 15:06:59 -05:00
|
|
|
|
context 'staged users' do
|
|
|
|
|
let(:staged) { Fabricate(:staged) }
|
|
|
|
|
let(:result) { Search.execute(staged.username) }
|
|
|
|
|
|
|
|
|
|
it 'does not return a result' do
|
|
|
|
|
expect(result.users.length).to eq(0)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2014-12-03 21:46:52 -05:00
|
|
|
|
context 'private messages' do
|
|
|
|
|
|
|
|
|
|
let(:topic) {
|
|
|
|
|
Fabricate(:topic,
|
|
|
|
|
category_id: nil,
|
|
|
|
|
archetype: 'private_message')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let(:post) { Fabricate(:post, topic: topic) }
|
|
|
|
|
let(:reply) { Fabricate(:post, topic: topic,
|
|
|
|
|
raw: 'hello from mars, we just landed') }
|
|
|
|
|
|
|
|
|
|
it 'searches correctly' do
|
|
|
|
|
|
2017-05-11 15:58:43 -04:00
|
|
|
|
expect do
|
2017-07-27 21:20:09 -04:00
|
|
|
|
Search.execute('mars', type_filter: 'private_messages')
|
2017-05-11 15:58:43 -04:00
|
|
|
|
end.to raise_error(Discourse::InvalidAccess)
|
2014-12-03 21:46:52 -05:00
|
|
|
|
|
2017-05-11 15:58:43 -04:00
|
|
|
|
TopicAllowedUser.create!(user_id: reply.user_id, topic_id: topic.id)
|
|
|
|
|
TopicAllowedUser.create!(user_id: post.user_id, topic_id: topic.id)
|
2014-12-03 21:46:52 -05:00
|
|
|
|
|
2017-05-11 15:58:43 -04:00
|
|
|
|
results = Search.execute('mars',
|
|
|
|
|
type_filter: 'private_messages',
|
|
|
|
|
guardian: Guardian.new(reply.user))
|
2014-12-03 21:46:52 -05:00
|
|
|
|
|
2017-05-11 15:58:43 -04:00
|
|
|
|
expect(results.posts.length).to eq(1)
|
2014-12-03 21:46:52 -05:00
|
|
|
|
|
2017-05-11 15:58:43 -04:00
|
|
|
|
results = Search.execute('mars',
|
|
|
|
|
search_context: topic,
|
|
|
|
|
guardian: Guardian.new(reply.user))
|
2015-02-18 20:56:49 -05:00
|
|
|
|
|
2017-05-11 15:58:43 -04:00
|
|
|
|
expect(results.posts.length).to eq(1)
|
2015-02-18 20:56:49 -05:00
|
|
|
|
|
2017-05-11 15:58:43 -04:00
|
|
|
|
# does not leak out
|
|
|
|
|
results = Search.execute('mars',
|
|
|
|
|
type_filter: 'private_messages',
|
|
|
|
|
guardian: Guardian.new(Fabricate(:user)))
|
2014-12-03 21:46:52 -05:00
|
|
|
|
|
2017-05-11 15:58:43 -04:00
|
|
|
|
expect(results.posts.length).to eq(0)
|
2014-12-03 21:46:52 -05:00
|
|
|
|
|
2017-05-11 15:58:43 -04:00
|
|
|
|
Fabricate(:topic, category_id: nil, archetype: 'private_message')
|
|
|
|
|
Fabricate(:post, topic: topic, raw: 'another secret pm from mars, testing')
|
2014-12-03 21:46:52 -05:00
|
|
|
|
|
2017-05-11 15:58:43 -04:00
|
|
|
|
# admin can search everything with correct context
|
|
|
|
|
results = Search.execute('mars',
|
|
|
|
|
type_filter: 'private_messages',
|
|
|
|
|
search_context: post.user,
|
|
|
|
|
guardian: Guardian.new(Fabricate(:admin)))
|
2014-12-03 21:46:52 -05:00
|
|
|
|
|
2017-05-11 15:58:43 -04:00
|
|
|
|
expect(results.posts.length).to eq(1)
|
2014-12-03 21:46:52 -05:00
|
|
|
|
|
2017-05-11 15:58:43 -04:00
|
|
|
|
results = Search.execute('mars in:private',
|
|
|
|
|
search_context: post.user,
|
|
|
|
|
guardian: Guardian.new(post.user))
|
2017-05-11 15:06:30 -04:00
|
|
|
|
|
2017-05-11 15:58:43 -04:00
|
|
|
|
expect(results.posts.length).to eq(1)
|
|
|
|
|
|
|
|
|
|
# can search group PMs as well as non admin
|
|
|
|
|
#
|
|
|
|
|
user = Fabricate(:user)
|
|
|
|
|
group = Fabricate.build(:group)
|
|
|
|
|
group.add(user)
|
|
|
|
|
group.save!
|
|
|
|
|
|
|
|
|
|
TopicAllowedGroup.create!(group_id: group.id, topic_id: topic.id)
|
|
|
|
|
|
|
|
|
|
results = Search.execute('mars in:private',
|
|
|
|
|
guardian: Guardian.new(user))
|
|
|
|
|
|
|
|
|
|
expect(results.posts.length).to eq(1)
|
2017-05-11 15:06:30 -04:00
|
|
|
|
|
2014-12-03 21:46:52 -05:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
2013-02-05 14:16:51 -05:00
|
|
|
|
context 'topics' do
|
2014-09-02 05:15:08 -04:00
|
|
|
|
let(:post) { Fabricate(:post) }
|
2017-07-27 21:20:09 -04:00
|
|
|
|
let(:topic) { post.topic }
|
2014-02-16 21:54:51 -05:00
|
|
|
|
|
|
|
|
|
context 'search within topic' do
|
|
|
|
|
|
2018-11-06 17:41:55 -05:00
|
|
|
|
def new_post(raw, topic = nil)
|
|
|
|
|
topic ||= Fabricate(:topic)
|
2014-02-16 21:54:51 -05:00
|
|
|
|
Fabricate(:post, topic: topic, topic_id: topic.id, user: topic.user, raw: raw)
|
|
|
|
|
end
|
|
|
|
|
|
2018-11-06 17:41:55 -05:00
|
|
|
|
it 'works in Chinese' do
|
|
|
|
|
SiteSetting.search_tokenize_chinese_japanese_korean = true
|
|
|
|
|
post = new_post('I am not in English 何点になると思いますか')
|
|
|
|
|
|
|
|
|
|
results = Search.execute('何点になると思', search_context: post.topic)
|
|
|
|
|
expect(results.posts.map(&:id)).to eq([post.id])
|
|
|
|
|
end
|
|
|
|
|
|
2014-02-16 21:54:51 -05:00
|
|
|
|
it 'displays multiple results within a topic' do
|
|
|
|
|
topic = Fabricate(:topic)
|
|
|
|
|
topic2 = Fabricate(:topic)
|
|
|
|
|
|
|
|
|
|
new_post('this is the other post I am posting', topic2)
|
2014-06-20 01:48:34 -04:00
|
|
|
|
new_post('this is my fifth post I am posting', topic2)
|
|
|
|
|
|
2014-02-16 21:54:51 -05:00
|
|
|
|
post1 = new_post('this is the other post I am posting', topic)
|
|
|
|
|
post2 = new_post('this is my first post I am posting', topic)
|
2018-05-07 05:43:55 -04:00
|
|
|
|
post3 = new_post('this is a real long and complicated bla this is my second post I am Posting birds with more stuff bla bla', topic)
|
2014-02-16 21:54:51 -05:00
|
|
|
|
post4 = new_post('this is my fourth post I am posting', topic)
|
|
|
|
|
|
2014-02-18 16:59:18 -05:00
|
|
|
|
# update posts_count
|
|
|
|
|
topic.reload
|
|
|
|
|
|
2014-09-02 05:15:08 -04:00
|
|
|
|
results = Search.execute('posting', search_context: post1.topic)
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(results.posts.map(&:id)).to eq([post1.id, post2.id, post3.id, post4.id])
|
2014-02-16 21:54:51 -05:00
|
|
|
|
|
2017-05-24 11:24:41 -04:00
|
|
|
|
results = Search.execute('posting l', search_context: post1.topic)
|
|
|
|
|
expect(results.posts.map(&:id)).to eq([post4.id, post3.id, post2.id, post1.id])
|
|
|
|
|
|
2014-06-20 01:48:34 -04:00
|
|
|
|
# stop words should work
|
2014-09-02 05:15:08 -04:00
|
|
|
|
results = Search.execute('this', search_context: post1.topic)
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(results.posts.length).to eq(4)
|
2016-07-25 01:06:25 -04:00
|
|
|
|
|
|
|
|
|
# phrase search works as expected
|
|
|
|
|
results = Search.execute('"fourth post I am posting"', search_context: post1.topic)
|
|
|
|
|
expect(results.posts.length).to eq(1)
|
2014-02-16 21:54:51 -05:00
|
|
|
|
end
|
2018-05-07 05:43:55 -04:00
|
|
|
|
|
|
|
|
|
it "works for unlisted topics" do
|
|
|
|
|
topic.update_attributes(visible: false)
|
2018-05-08 01:59:03 -04:00
|
|
|
|
_post = new_post('discourse is awesome', topic)
|
2018-05-07 05:43:55 -04:00
|
|
|
|
results = Search.execute('discourse', search_context: topic)
|
|
|
|
|
expect(results.posts.length).to eq(1)
|
|
|
|
|
end
|
2014-02-16 21:54:51 -05:00
|
|
|
|
end
|
|
|
|
|
|
2013-02-25 11:42:20 -05:00
|
|
|
|
context 'searching the OP' do
|
2014-09-02 05:15:08 -04:00
|
|
|
|
let!(:post) { Fabricate(:post_with_long_raw_content) }
|
|
|
|
|
let(:result) { Search.execute('hundred', type_filter: 'topic', include_blurbs: true) }
|
2013-02-05 14:16:51 -05:00
|
|
|
|
|
2013-05-12 20:48:32 -04:00
|
|
|
|
it 'returns a result correctly' do
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(result.posts.length).to eq(1)
|
|
|
|
|
expect(result.posts[0].id).to eq(post.id)
|
2013-02-05 14:16:51 -05:00
|
|
|
|
end
|
2013-05-13 17:04:41 -04:00
|
|
|
|
end
|
|
|
|
|
|
2013-06-28 21:22:17 -04:00
|
|
|
|
context 'searching for a post' do
|
2019-03-26 05:01:19 -04:00
|
|
|
|
let!(:reply) do
|
|
|
|
|
Fabricate(:post_with_long_raw_content,
|
|
|
|
|
topic: topic,
|
|
|
|
|
user: topic.user,
|
|
|
|
|
).tap { |post| post.update!(raw: "#{post.raw} elephant") }
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
let(:expected_blurb) do
|
|
|
|
|
"...to satisfy any test conditions that require content longer than the typical test post raw content. elephant"
|
|
|
|
|
end
|
2013-06-28 21:22:17 -04:00
|
|
|
|
|
|
|
|
|
it 'returns the post' do
|
2019-03-26 05:01:19 -04:00
|
|
|
|
result = Search.execute('elephant',
|
|
|
|
|
type_filter: 'topic',
|
|
|
|
|
include_blurbs: true
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
expect(result.posts).to contain_exactly(reply)
|
|
|
|
|
expect(result.blurb(reply)).to eq(expected_blurb)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'returns the right post and blurb for searches with phrase' do
|
|
|
|
|
result = Search.execute('"elephant"',
|
|
|
|
|
type_filter: 'topic',
|
|
|
|
|
include_blurbs: true
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
expect(result.posts).to contain_exactly(reply)
|
|
|
|
|
expect(result.blurb(reply)).to eq(expected_blurb)
|
2013-06-28 21:22:17 -04:00
|
|
|
|
end
|
2019-04-01 01:40:11 -04:00
|
|
|
|
|
|
|
|
|
it 'does not allow a post with repeated words to dominate the ranking' do
|
|
|
|
|
category = Fabricate(:category, name: "winter is coming")
|
|
|
|
|
|
|
|
|
|
post = Fabricate(:post,
|
|
|
|
|
raw: "I think winter will end soon",
|
|
|
|
|
topic: Fabricate(:topic,
|
|
|
|
|
title: "dragon john snow winter",
|
|
|
|
|
category: category
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
post2 = Fabricate(:post,
|
2019-04-03 04:04:00 -04:00
|
|
|
|
raw: "I think #{'winter' * 20} will end soon",
|
2019-04-01 01:40:11 -04:00
|
|
|
|
topic: Fabricate(:topic, title: "dragon john snow summer", category: category)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
result = Search.execute('winter')
|
|
|
|
|
|
2019-04-03 04:04:00 -04:00
|
|
|
|
expect(result.posts.pluck(:id)).to eq([
|
|
|
|
|
post.id, category.topic.first_post.id, post2.id
|
|
|
|
|
])
|
2019-04-01 01:40:11 -04:00
|
|
|
|
end
|
2013-06-28 21:22:17 -04:00
|
|
|
|
end
|
|
|
|
|
|
2018-05-08 01:59:03 -04:00
|
|
|
|
context 'searching for quoted title' do
|
|
|
|
|
it "can find quoted title" do
|
|
|
|
|
create_post(raw: "this is the raw body", title: "I am a title yeah")
|
|
|
|
|
result = Search.execute('"a title yeah"')
|
|
|
|
|
|
|
|
|
|
expect(result.posts.length).to eq(1)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
2014-08-28 15:42:29 -04:00
|
|
|
|
context "search for a topic by id" do
|
2014-09-02 05:15:08 -04:00
|
|
|
|
let(:result) { Search.execute(topic.id, type_filter: 'topic', search_for_id: true, min_search_term_length: 1) }
|
2014-08-28 15:42:29 -04:00
|
|
|
|
|
|
|
|
|
it 'returns the topic' do
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(result.posts.length).to eq(1)
|
|
|
|
|
expect(result.posts.first.id).to eq(post.id)
|
2014-08-28 15:42:29 -04:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2013-05-13 17:04:41 -04:00
|
|
|
|
context "search for a topic by url" do
|
|
|
|
|
it 'returns the topic' do
|
2019-01-14 04:30:45 -05:00
|
|
|
|
result = Search.execute(topic.relative_url, search_for_id: true, type_filter: 'topic')
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(result.posts.length).to eq(1)
|
|
|
|
|
expect(result.posts.first.id).to eq(post.id)
|
2013-05-13 17:04:41 -04:00
|
|
|
|
end
|
2019-01-14 04:30:45 -05:00
|
|
|
|
|
|
|
|
|
context 'restrict_to_archetype' do
|
|
|
|
|
let(:personal_message) { Fabricate(:private_message_topic) }
|
|
|
|
|
let!(:p1) { Fabricate(:post, topic: personal_message, post_number: 1) }
|
|
|
|
|
|
|
|
|
|
it 'restricts result to topics' do
|
|
|
|
|
result = Search.execute(personal_message.relative_url, search_for_id: true, type_filter: 'topic', restrict_to_archetype: Archetype.default)
|
|
|
|
|
expect(result.posts.length).to eq(0)
|
|
|
|
|
|
|
|
|
|
result = Search.execute(topic.relative_url, search_for_id: true, type_filter: 'topic', restrict_to_archetype: Archetype.default)
|
|
|
|
|
expect(result.posts.length).to eq(1)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'restricts result to messages' do
|
|
|
|
|
result = Search.execute(topic.relative_url, search_for_id: true, type_filter: 'private_messages', guardian: Guardian.new(Fabricate(:admin)), restrict_to_archetype: Archetype.private_message)
|
|
|
|
|
expect(result.posts.length).to eq(0)
|
|
|
|
|
|
|
|
|
|
result = Search.execute(personal_message.relative_url, search_for_id: true, type_filter: 'private_messages', guardian: Guardian.new(Fabricate(:admin)), restrict_to_archetype: Archetype.private_message)
|
|
|
|
|
expect(result.posts.length).to eq(1)
|
|
|
|
|
end
|
|
|
|
|
end
|
2013-05-12 20:48:32 -04:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'security' do
|
2013-06-28 21:22:17 -04:00
|
|
|
|
|
2013-05-12 20:48:32 -04:00
|
|
|
|
def result(current_user)
|
2014-10-18 00:19:08 -04:00
|
|
|
|
Search.execute('hello', guardian: Guardian.new(current_user))
|
2013-02-05 14:16:51 -05:00
|
|
|
|
end
|
|
|
|
|
|
2013-05-12 20:48:32 -04:00
|
|
|
|
it 'secures results correctly' do
|
|
|
|
|
category = Fabricate(:category)
|
|
|
|
|
|
|
|
|
|
topic.category_id = category.id
|
|
|
|
|
topic.save
|
|
|
|
|
|
2017-07-27 21:20:09 -04:00
|
|
|
|
category.set_permissions(staff: :full)
|
2013-05-12 20:48:32 -04:00
|
|
|
|
category.save
|
|
|
|
|
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(result(nil).posts).not_to be_present
|
|
|
|
|
expect(result(Fabricate(:user)).posts).not_to be_present
|
|
|
|
|
expect(result(Fabricate(:admin)).posts).to be_present
|
2013-05-12 20:48:32 -04:00
|
|
|
|
|
2013-02-25 11:42:20 -05:00
|
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
2013-02-28 14:52:35 -05:00
|
|
|
|
context 'cyrillic topic' do
|
|
|
|
|
let!(:cyrillic_topic) { Fabricate(:topic) do
|
2017-07-27 21:20:09 -04:00
|
|
|
|
user
|
2013-02-28 14:52:35 -05:00
|
|
|
|
title { sequence(:title) { |i| "Тестовая запись #{i}" } }
|
2017-07-27 21:20:09 -04:00
|
|
|
|
end
|
2013-02-28 14:52:35 -05:00
|
|
|
|
}
|
2017-07-27 21:20:09 -04:00
|
|
|
|
let!(:post) { Fabricate(:post, topic: cyrillic_topic, user: cyrillic_topic.user) }
|
2014-09-02 05:15:08 -04:00
|
|
|
|
let(:result) { Search.execute('запись') }
|
2013-02-28 14:52:35 -05:00
|
|
|
|
|
|
|
|
|
it 'finds something when given cyrillic query' do
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(result.posts).to be_present
|
2013-02-28 14:52:35 -05:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2016-10-06 21:40:57 -04:00
|
|
|
|
it 'does not tokenize search term' do
|
|
|
|
|
Fabricate(:post, raw: 'thing is canned should still be found!')
|
|
|
|
|
expect(Search.execute('canned').posts).to be_present
|
|
|
|
|
end
|
|
|
|
|
|
2013-02-05 14:16:51 -05:00
|
|
|
|
context 'categories' do
|
2019-03-18 03:25:45 -04:00
|
|
|
|
let(:category) { Fabricate(:category, name: "monkey Category 2") }
|
|
|
|
|
let(:topic) { Fabricate(:topic, category: category) }
|
|
|
|
|
let!(:post) { Fabricate(:post, topic: topic, raw: "snow monkey") }
|
2013-02-05 14:16:51 -05:00
|
|
|
|
|
2019-03-18 03:25:45 -04:00
|
|
|
|
let!(:ignored_category) do
|
|
|
|
|
Fabricate(:category,
|
|
|
|
|
name: "monkey Category 1",
|
2019-03-18 23:23:14 -04:00
|
|
|
|
slug: "test",
|
2019-03-18 03:25:45 -04:00
|
|
|
|
search_priority: Searchable::PRIORITIES[:ignore]
|
|
|
|
|
)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it "should return the right categories" do
|
|
|
|
|
search = Search.execute("monkey")
|
|
|
|
|
|
|
|
|
|
expect(search.categories).to contain_exactly(
|
|
|
|
|
category, ignored_category
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
expect(search.posts).to contain_exactly(category.topic.first_post, post)
|
2019-03-18 23:23:14 -04:00
|
|
|
|
|
|
|
|
|
search = Search.execute("monkey #test")
|
|
|
|
|
|
|
|
|
|
expect(search.posts).to contain_exactly(ignored_category.topic.first_post)
|
2013-05-13 04:04:03 -04:00
|
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
|
|
2019-03-18 03:25:45 -04:00
|
|
|
|
describe "with child categories" do
|
|
|
|
|
let!(:child_of_ignored_category) do
|
|
|
|
|
Fabricate(:category,
|
|
|
|
|
name: "monkey Category 3",
|
|
|
|
|
parent_category: ignored_category
|
|
|
|
|
)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
let!(:post2) do
|
|
|
|
|
Fabricate(:post,
|
|
|
|
|
topic: Fabricate(:topic, category: child_of_ignored_category),
|
|
|
|
|
raw: "snow monkey park"
|
|
|
|
|
)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'returns the right results' do
|
|
|
|
|
search = Search.execute("monkey")
|
|
|
|
|
|
|
|
|
|
expect(search.categories).to contain_exactly(
|
|
|
|
|
category, ignored_category, child_of_ignored_category
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
expect(search.posts).to contain_exactly(
|
|
|
|
|
category.topic.first_post,
|
|
|
|
|
post,
|
|
|
|
|
child_of_ignored_category.topic.first_post,
|
|
|
|
|
post2
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
search = Search.execute("snow")
|
|
|
|
|
expect(search.posts).to contain_exactly(post, post2)
|
2013-05-13 04:04:03 -04:00
|
|
|
|
|
2019-03-18 03:25:45 -04:00
|
|
|
|
category.set_permissions({})
|
|
|
|
|
category.save
|
|
|
|
|
search = Search.execute("monkey")
|
|
|
|
|
|
|
|
|
|
expect(search.categories).to contain_exactly(
|
|
|
|
|
ignored_category, child_of_ignored_category
|
|
|
|
|
)
|
2013-05-13 04:04:03 -04:00
|
|
|
|
|
2019-03-18 03:25:45 -04:00
|
|
|
|
expect(search.posts).to contain_exactly(
|
|
|
|
|
child_of_ignored_category.topic.first_post,
|
|
|
|
|
post2
|
|
|
|
|
)
|
|
|
|
|
end
|
2013-02-25 11:42:20 -05:00
|
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
|
|
2019-03-24 22:59:55 -04:00
|
|
|
|
describe 'categories with different priorities' do
|
|
|
|
|
let(:category2) { Fabricate(:category) }
|
|
|
|
|
|
|
|
|
|
it "should return posts in the right order" do
|
|
|
|
|
raw = "The pure genuine evian"
|
|
|
|
|
post = Fabricate(:post, topic: category.topic, raw: raw)
|
|
|
|
|
post2 = Fabricate(:post, topic: category2.topic, raw: raw)
|
|
|
|
|
|
|
|
|
|
search = Search.execute(raw)
|
|
|
|
|
|
|
|
|
|
expect(search.posts).to eq([post2, post])
|
|
|
|
|
|
|
|
|
|
category.update!(search_priority: Searchable::PRIORITIES[:high])
|
|
|
|
|
|
|
|
|
|
search = Search.execute(raw)
|
|
|
|
|
|
|
|
|
|
expect(search.posts).to eq([post, post2])
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2013-02-05 14:16:51 -05:00
|
|
|
|
end
|
|
|
|
|
|
2019-03-04 04:30:09 -05:00
|
|
|
|
context 'groups' do
|
|
|
|
|
def search(user = Fabricate(:user))
|
|
|
|
|
Search.execute(group.name, guardian: Guardian.new(user))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
let!(:group) { Group[:trust_level_0] }
|
|
|
|
|
|
|
|
|
|
it 'shows group' do
|
|
|
|
|
expect(search.groups.map(&:name)).to eq([group.name])
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'group visibility' do
|
|
|
|
|
let!(:group) { Fabricate(:group) }
|
|
|
|
|
|
|
|
|
|
before do
|
|
|
|
|
group.update!(visibility_level: 3)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'staff logged in' do
|
|
|
|
|
it 'shows group' do
|
|
|
|
|
expect(search(Fabricate(:admin)).groups.map(&:name)).to eq([group.name])
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'non staff logged in' do
|
|
|
|
|
it 'shows doesn’t show group' do
|
|
|
|
|
expect(search.groups.map(&:name)).to be_empty
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2017-08-25 11:52:18 -04:00
|
|
|
|
context 'tags' do
|
|
|
|
|
def search
|
|
|
|
|
Search.execute(tag.name)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
let!(:tag) { Fabricate(:tag) }
|
2018-10-05 05:23:52 -04:00
|
|
|
|
let!(:uppercase_tag) { Fabricate(:tag, name: "HeLlO") }
|
2017-08-25 11:52:18 -04:00
|
|
|
|
let(:tag_group) { Fabricate(:tag_group) }
|
|
|
|
|
let(:category) { Fabricate(:category) }
|
|
|
|
|
|
2018-02-19 22:41:00 -05:00
|
|
|
|
context 'post searching' do
|
|
|
|
|
it 'can find posts with tags' do
|
|
|
|
|
SiteSetting.tagging_enabled = true
|
|
|
|
|
|
|
|
|
|
post = Fabricate(:post, raw: 'I am special post')
|
2018-10-05 05:23:52 -04:00
|
|
|
|
DiscourseTagging.tag_topic_by_names(post.topic, Guardian.new(Fabricate.build(:admin)), [tag.name, uppercase_tag.name])
|
2018-02-19 22:41:00 -05:00
|
|
|
|
post.topic.save
|
|
|
|
|
|
|
|
|
|
# we got to make this index (it is deferred)
|
|
|
|
|
Jobs::ReindexSearch.new.rebuild_problem_posts
|
|
|
|
|
|
|
|
|
|
result = Search.execute(tag.name)
|
|
|
|
|
expect(result.posts.length).to eq(1)
|
|
|
|
|
|
2018-10-05 05:23:52 -04:00
|
|
|
|
result = Search.execute("hElLo")
|
|
|
|
|
expect(result.posts.length).to eq(1)
|
|
|
|
|
|
2018-02-19 22:41:00 -05:00
|
|
|
|
SiteSetting.tagging_enabled = false
|
|
|
|
|
|
|
|
|
|
result = Search.execute(tag.name)
|
|
|
|
|
expect(result.posts.length).to eq(0)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2017-08-25 11:52:18 -04:00
|
|
|
|
context 'tagging is disabled' do
|
|
|
|
|
before { SiteSetting.tagging_enabled = false }
|
|
|
|
|
|
|
|
|
|
it 'does not include tags' do
|
|
|
|
|
expect(search.tags).to_not be_present
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'tagging is enabled' do
|
|
|
|
|
before { SiteSetting.tagging_enabled = true }
|
|
|
|
|
|
|
|
|
|
it 'returns the tag in the result' do
|
|
|
|
|
expect(search.tags).to eq([tag])
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'shows staff tags' do
|
2018-04-20 15:25:28 -04:00
|
|
|
|
create_staff_tags(["#{tag.name}9"])
|
2017-08-25 11:52:18 -04:00
|
|
|
|
|
2018-04-20 15:25:28 -04:00
|
|
|
|
expect(Search.execute(tag.name, guardian: Guardian.new(Fabricate(:admin))).tags.map(&:name)).to contain_exactly(tag.name, "#{tag.name}9")
|
|
|
|
|
expect(search.tags.map(&:name)).to contain_exactly(tag.name, "#{tag.name}9")
|
2017-08-25 11:52:18 -04:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'includes category-restricted tags' do
|
|
|
|
|
category_tag = Fabricate(:tag, name: "#{tag.name}9")
|
|
|
|
|
tag_group.tags = [category_tag]
|
|
|
|
|
category.set_permissions(admins: :full)
|
|
|
|
|
category.allowed_tag_groups = [tag_group.name]
|
|
|
|
|
category.save!
|
|
|
|
|
|
|
|
|
|
expect(Search.execute(tag.name, guardian: Guardian.new(Fabricate(:admin))).tags).to contain_exactly(tag, category_tag)
|
|
|
|
|
expect(search.tags).to contain_exactly(tag, category_tag)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2013-02-05 14:16:51 -05:00
|
|
|
|
context 'type_filter' do
|
|
|
|
|
|
|
|
|
|
let!(:user) { Fabricate(:user, username: 'amazing', email: 'amazing@amazing.com') }
|
|
|
|
|
let!(:category) { Fabricate(:category, name: 'amazing category', user: user) }
|
2013-02-25 11:42:20 -05:00
|
|
|
|
|
2013-02-05 14:16:51 -05:00
|
|
|
|
context 'user filter' do
|
2014-09-02 05:15:08 -04:00
|
|
|
|
let(:results) { Search.execute('amazing', type_filter: 'user') }
|
2013-02-05 14:16:51 -05:00
|
|
|
|
|
|
|
|
|
it "returns a user result" do
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(results.categories.length).to eq(0)
|
|
|
|
|
expect(results.posts.length).to eq(0)
|
|
|
|
|
expect(results.users.length).to eq(1)
|
2013-02-05 14:16:51 -05:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'category filter' do
|
2014-09-02 05:15:08 -04:00
|
|
|
|
let(:results) { Search.execute('amazing', type_filter: 'category') }
|
2013-02-05 14:16:51 -05:00
|
|
|
|
|
2013-05-21 04:56:04 -04:00
|
|
|
|
it "returns a category result" do
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(results.categories.length).to eq(1)
|
|
|
|
|
expect(results.posts.length).to eq(0)
|
|
|
|
|
expect(results.users.length).to eq(0)
|
2013-02-05 14:16:51 -05:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
2013-05-24 14:03:45 -04:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'search_context' do
|
|
|
|
|
|
2014-09-02 05:15:08 -04:00
|
|
|
|
it 'can find a user when using search context' do
|
|
|
|
|
|
|
|
|
|
coding_horror = Fabricate(:coding_horror)
|
|
|
|
|
post = Fabricate(:post)
|
2013-05-24 14:03:45 -04:00
|
|
|
|
|
2014-09-02 05:15:08 -04:00
|
|
|
|
Fabricate(:post, user: coding_horror)
|
2013-05-24 16:17:09 -04:00
|
|
|
|
|
2014-09-02 05:15:08 -04:00
|
|
|
|
result = Search.execute('hello', search_context: post.user)
|
|
|
|
|
|
|
|
|
|
result.posts.first.topic_id = post.topic_id
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(result.posts.length).to eq(1)
|
2013-05-24 14:03:45 -04:00
|
|
|
|
end
|
|
|
|
|
|
2014-09-02 05:15:08 -04:00
|
|
|
|
it 'can use category as a search context' do
|
2019-03-18 03:25:45 -04:00
|
|
|
|
category = Fabricate(:category,
|
|
|
|
|
search_priority: Searchable::PRIORITIES[:ignore]
|
|
|
|
|
)
|
|
|
|
|
|
2014-09-02 05:15:08 -04:00
|
|
|
|
topic = Fabricate(:topic, category: category)
|
|
|
|
|
topic_no_cat = Fabricate(:topic)
|
|
|
|
|
|
2017-03-10 15:58:47 -05:00
|
|
|
|
# includes subcategory in search
|
|
|
|
|
subcategory = Fabricate(:category, parent_category_id: category.id)
|
|
|
|
|
sub_topic = Fabricate(:topic, category: subcategory)
|
|
|
|
|
|
2017-07-27 21:20:09 -04:00
|
|
|
|
post = Fabricate(:post, topic: topic, user: topic.user)
|
|
|
|
|
_another_post = Fabricate(:post, topic: topic_no_cat, user: topic.user)
|
|
|
|
|
sub_post = Fabricate(:post, raw: 'I am saying hello from a subcategory', topic: sub_topic, user: topic.user)
|
2013-05-24 14:03:45 -04:00
|
|
|
|
|
2014-09-02 05:15:08 -04:00
|
|
|
|
search = Search.execute('hello', search_context: category)
|
2017-07-27 21:20:09 -04:00
|
|
|
|
expect(search.posts.map(&:id).sort).to eq([post.id, sub_post.id].sort)
|
2017-03-10 15:58:47 -05:00
|
|
|
|
expect(search.posts.length).to eq(2)
|
2013-05-24 14:03:45 -04:00
|
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
2014-06-25 19:58:49 -04:00
|
|
|
|
describe 'Chinese search' do
|
2017-07-31 15:28:48 -04:00
|
|
|
|
let(:sentence) { 'Discourse中国的基础设施网络正在组装' }
|
|
|
|
|
let(:sentence_t) { 'Discourse太平山森林遊樂區' }
|
|
|
|
|
|
|
|
|
|
it 'splits English / Chinese and filter out stop words' do
|
2014-06-25 19:58:49 -04:00
|
|
|
|
SiteSetting.default_locale = 'zh_CN'
|
2017-07-31 15:28:48 -04:00
|
|
|
|
data = Search.prepare_data(sentence).split(' ')
|
|
|
|
|
expect(data).to eq(["Discourse", "中国", "基础", "设施", "基础设施", "网络", "正在", "组装"])
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'splits for indexing and filter out stop words' do
|
|
|
|
|
SiteSetting.default_locale = 'zh_CN'
|
|
|
|
|
data = Search.prepare_data(sentence, :index).split(' ')
|
|
|
|
|
expect(data).to eq(["Discourse", "中国", "基础设施", "网络", "正在", "组装"])
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'splits English / Traditional Chinese and filter out stop words' do
|
|
|
|
|
SiteSetting.default_locale = 'zh_TW'
|
|
|
|
|
data = Search.prepare_data(sentence_t).split(' ')
|
|
|
|
|
expect(data).to eq(["Discourse", "太平", "平山", "太平山", "森林", "遊樂區"])
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'splits for indexing and filter out stop words' do
|
|
|
|
|
SiteSetting.default_locale = 'zh_TW'
|
|
|
|
|
data = Search.prepare_data(sentence_t, :index).split(' ')
|
|
|
|
|
expect(data).to eq(["Discourse", "太平山", "森林", "遊樂區"])
|
2014-06-25 19:58:49 -04:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'finds chinese topic based on title' do
|
2015-04-23 17:22:46 -04:00
|
|
|
|
skip("skipped until pg app installs the db correctly") if RbConfig::CONFIG["arch"] =~ /darwin/
|
|
|
|
|
|
2014-06-25 19:58:49 -04:00
|
|
|
|
SiteSetting.default_locale = 'zh_TW'
|
2016-08-09 15:20:28 -04:00
|
|
|
|
SiteSetting.min_search_term_length = 1
|
2014-09-16 07:15:05 -04:00
|
|
|
|
topic = Fabricate(:topic, title: 'My Title Discourse社區指南')
|
2014-09-02 05:15:08 -04:00
|
|
|
|
post = Fabricate(:post, topic: topic)
|
2014-06-25 19:58:49 -04:00
|
|
|
|
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(Search.execute('社區指南').posts.first.id).to eq(post.id)
|
|
|
|
|
expect(Search.execute('指南').posts.first.id).to eq(post.id)
|
2014-06-25 19:58:49 -04:00
|
|
|
|
end
|
2015-11-27 00:35:27 -05:00
|
|
|
|
|
|
|
|
|
it 'finds chinese topic based on title if tokenization is forced' do
|
|
|
|
|
skip("skipped until pg app installs the db correctly") if RbConfig::CONFIG["arch"] =~ /darwin/
|
|
|
|
|
|
|
|
|
|
SiteSetting.search_tokenize_chinese_japanese_korean = true
|
2016-08-09 15:20:28 -04:00
|
|
|
|
SiteSetting.min_search_term_length = 1
|
2015-11-27 00:35:27 -05:00
|
|
|
|
|
|
|
|
|
topic = Fabricate(:topic, title: 'My Title Discourse社區指南')
|
|
|
|
|
post = Fabricate(:post, topic: topic)
|
|
|
|
|
|
|
|
|
|
expect(Search.execute('社區指南').posts.first.id).to eq(post.id)
|
|
|
|
|
expect(Search.execute('指南').posts.first.id).to eq(post.id)
|
|
|
|
|
end
|
2014-06-25 19:58:49 -04:00
|
|
|
|
end
|
|
|
|
|
|
2014-09-03 07:54:10 -04:00
|
|
|
|
describe 'Advanced search' do
|
2015-06-22 23:21:50 -04:00
|
|
|
|
|
2016-03-18 01:26:54 -04:00
|
|
|
|
it 'supports pinned and unpinned' do
|
|
|
|
|
topic = Fabricate(:topic)
|
|
|
|
|
Fabricate(:post, raw: 'hi this is a test 123 123', topic: topic)
|
|
|
|
|
_post = Fabricate(:post, raw: 'boom boom shake the room', topic: topic)
|
|
|
|
|
|
|
|
|
|
topic.update_pinned(true)
|
|
|
|
|
|
|
|
|
|
user = Fabricate(:user)
|
|
|
|
|
guardian = Guardian.new(user)
|
|
|
|
|
|
|
|
|
|
expect(Search.execute('boom in:pinned').posts.length).to eq(1)
|
|
|
|
|
expect(Search.execute('boom in:unpinned', guardian: guardian).posts.length).to eq(0)
|
|
|
|
|
|
|
|
|
|
topic.clear_pin_for(user)
|
|
|
|
|
|
|
|
|
|
expect(Search.execute('boom in:unpinned', guardian: guardian).posts.length).to eq(1)
|
|
|
|
|
end
|
|
|
|
|
|
2016-05-13 04:26:53 -04:00
|
|
|
|
it 'supports wiki' do
|
|
|
|
|
topic = Fabricate(:topic)
|
2017-03-08 09:46:23 -05:00
|
|
|
|
topic_2 = Fabricate(:topic)
|
|
|
|
|
post = Fabricate(:post, raw: 'this is a test 248', wiki: true, topic: topic)
|
|
|
|
|
Fabricate(:post, raw: 'this is a test 248', wiki: false, topic: topic_2)
|
2016-05-13 04:26:53 -04:00
|
|
|
|
|
2017-03-08 09:46:23 -05:00
|
|
|
|
expect(Search.execute('test 248').posts.length).to eq(2)
|
|
|
|
|
expect(Search.execute('test 248 in:wiki').posts.first).to eq(post)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'supports searching for posts that the user has seen/unseen' do
|
|
|
|
|
topic = Fabricate(:topic)
|
|
|
|
|
topic_2 = Fabricate(:topic)
|
|
|
|
|
post = Fabricate(:post, raw: 'logan is longan', topic: topic)
|
|
|
|
|
post_2 = Fabricate(:post, raw: 'longan is logan', topic: topic_2)
|
|
|
|
|
|
|
|
|
|
[post.user, topic.user].each do |user|
|
|
|
|
|
PostTiming.create!(
|
|
|
|
|
post_number: post.post_number,
|
|
|
|
|
topic: topic,
|
|
|
|
|
user: user,
|
|
|
|
|
msecs: 1
|
|
|
|
|
)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
expect(post.seen?(post.user)).to eq(true)
|
|
|
|
|
|
|
|
|
|
expect(Search.execute('longan').posts.sort).to eq([post, post_2])
|
|
|
|
|
|
|
|
|
|
expect(Search.execute('longan in:seen', guardian: Guardian.new(post.user)).posts)
|
|
|
|
|
.to eq([post])
|
|
|
|
|
|
|
|
|
|
expect(Search.execute('longan in:seen').posts.sort).to eq([post, post_2])
|
|
|
|
|
|
|
|
|
|
expect(Search.execute('longan in:seen', guardian: Guardian.new(post_2.user)).posts)
|
|
|
|
|
.to eq([])
|
|
|
|
|
|
|
|
|
|
expect(Search.execute('longan', guardian: Guardian.new(post_2.user)).posts.sort)
|
|
|
|
|
.to eq([post, post_2])
|
|
|
|
|
|
|
|
|
|
expect(Search.execute('longan in:unseen', guardian: Guardian.new(post_2.user)).posts.sort)
|
|
|
|
|
.to eq([post, post_2])
|
|
|
|
|
|
|
|
|
|
expect(Search.execute('longan in:unseen', guardian: Guardian.new(post.user)).posts)
|
|
|
|
|
.to eq([post_2])
|
2016-05-13 04:26:53 -04:00
|
|
|
|
end
|
|
|
|
|
|
2016-05-12 04:43:44 -04:00
|
|
|
|
it 'supports before and after, in:first, user:, @username' do
|
2016-03-14 08:27:02 -04:00
|
|
|
|
|
|
|
|
|
time = Time.zone.parse('2001-05-20 2:55')
|
|
|
|
|
freeze_time(time)
|
|
|
|
|
|
|
|
|
|
topic = Fabricate(:topic)
|
|
|
|
|
Fabricate(:post, raw: 'hi this is a test 123 123', topic: topic, created_at: time.months_ago(2))
|
2015-08-13 21:53:16 -04:00
|
|
|
|
_post = Fabricate(:post, raw: 'boom boom shake the room', topic: topic)
|
2015-06-22 23:21:50 -04:00
|
|
|
|
|
2016-03-14 08:27:02 -04:00
|
|
|
|
expect(Search.execute('test before:1').posts.length).to eq(1)
|
|
|
|
|
expect(Search.execute('test before:2001-04-20').posts.length).to eq(1)
|
|
|
|
|
expect(Search.execute('test before:2001').posts.length).to eq(0)
|
|
|
|
|
expect(Search.execute('test before:monday').posts.length).to eq(1)
|
|
|
|
|
|
|
|
|
|
expect(Search.execute('test after:jan').posts.length).to eq(1)
|
2015-06-22 23:21:50 -04:00
|
|
|
|
|
2015-06-22 23:39:40 -04:00
|
|
|
|
expect(Search.execute('test in:first').posts.length).to eq(1)
|
2019-02-24 18:55:24 -05:00
|
|
|
|
|
2015-06-22 23:39:40 -04:00
|
|
|
|
expect(Search.execute('boom').posts.length).to eq(1)
|
2019-02-24 18:55:24 -05:00
|
|
|
|
|
2015-06-22 23:39:40 -04:00
|
|
|
|
expect(Search.execute('boom in:first').posts.length).to eq(0)
|
2019-02-24 18:55:24 -05:00
|
|
|
|
expect(Search.execute('boom f').posts.length).to eq(0)
|
|
|
|
|
|
|
|
|
|
expect(Search.execute('123 in:first').posts.length).to eq(1)
|
|
|
|
|
expect(Search.execute('123 f').posts.length).to eq(1)
|
2015-06-22 23:39:40 -04:00
|
|
|
|
|
2015-08-13 21:53:16 -04:00
|
|
|
|
expect(Search.execute('user:nobody').posts.length).to eq(0)
|
|
|
|
|
expect(Search.execute("user:#{_post.user.username}").posts.length).to eq(1)
|
2015-11-18 15:06:59 -05:00
|
|
|
|
expect(Search.execute("user:#{_post.user_id}").posts.length).to eq(1)
|
2016-05-12 04:43:44 -04:00
|
|
|
|
|
|
|
|
|
expect(Search.execute("@#{_post.user.username}").posts.length).to eq(1)
|
2015-06-22 23:21:50 -04:00
|
|
|
|
end
|
|
|
|
|
|
2015-09-15 03:39:14 -04:00
|
|
|
|
it 'supports group' do
|
|
|
|
|
topic = Fabricate(:topic, created_at: 3.months.ago)
|
|
|
|
|
post = Fabricate(:post, raw: 'hi this is a test 123 123', topic: topic)
|
|
|
|
|
|
|
|
|
|
group = Group.create!(name: "Like_a_Boss")
|
|
|
|
|
GroupUser.create!(user_id: post.user_id, group_id: group.id)
|
|
|
|
|
|
|
|
|
|
expect(Search.execute('group:like_a_boss').posts.length).to eq(1)
|
|
|
|
|
expect(Search.execute('group:"like a brick"').posts.length).to eq(0)
|
|
|
|
|
end
|
|
|
|
|
|
2015-09-15 04:47:27 -04:00
|
|
|
|
it 'supports badge' do
|
2015-09-15 03:21:46 -04:00
|
|
|
|
|
|
|
|
|
topic = Fabricate(:topic, created_at: 3.months.ago)
|
|
|
|
|
post = Fabricate(:post, raw: 'hi this is a test 123 123', topic: topic)
|
|
|
|
|
|
|
|
|
|
badge = Badge.create!(name: "Like a Boss", badge_type_id: 1)
|
|
|
|
|
UserBadge.create!(user_id: post.user_id, badge_id: badge.id, granted_at: 1.minute.ago, granted_by_id: -1)
|
|
|
|
|
|
2015-09-15 04:47:27 -04:00
|
|
|
|
expect(Search.execute('badge:"like a boss"').posts.length).to eq(1)
|
|
|
|
|
expect(Search.execute('badge:"test"').posts.length).to eq(0)
|
2015-09-15 03:21:46 -04:00
|
|
|
|
end
|
|
|
|
|
|
2015-08-10 03:41:14 -04:00
|
|
|
|
it 'can search numbers correctly, and match exact phrases' do
|
2019-03-26 04:31:15 -04:00
|
|
|
|
post = Fabricate(:post, raw: '3.0 eta is in 2 days horrah')
|
|
|
|
|
post2 = Fabricate(:post, raw: '3.0 is eta in 2 days horrah')
|
2015-08-10 03:41:14 -04:00
|
|
|
|
|
2019-03-26 04:31:15 -04:00
|
|
|
|
expect(Search.execute('3.0 eta').posts).to contain_exactly(post, post2)
|
|
|
|
|
expect(Search.execute("'3.0 eta'").posts).to contain_exactly(post, post2)
|
|
|
|
|
expect(Search.execute("\"3.0 eta\"").posts).to contain_exactly(post)
|
|
|
|
|
expect(Search.execute('"3.0, eta is"').posts).to eq([])
|
2015-08-10 03:41:14 -04:00
|
|
|
|
end
|
|
|
|
|
|
2014-09-03 07:54:10 -04:00
|
|
|
|
it 'can find by status' do
|
|
|
|
|
post = Fabricate(:post, raw: 'hi this is a test 123 123')
|
|
|
|
|
topic = post.topic
|
|
|
|
|
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(Search.execute('test status:closed').posts.length).to eq(0)
|
|
|
|
|
expect(Search.execute('test status:open').posts.length).to eq(1)
|
2015-06-22 22:14:06 -04:00
|
|
|
|
expect(Search.execute('test posts_count:1').posts.length).to eq(1)
|
2016-11-28 09:57:18 -05:00
|
|
|
|
expect(Search.execute('test min_post_count:1').posts.length).to eq(1)
|
2014-09-03 07:54:10 -04:00
|
|
|
|
|
|
|
|
|
topic.closed = true
|
|
|
|
|
topic.save
|
|
|
|
|
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(Search.execute('test status:closed').posts.length).to eq(1)
|
2015-06-22 22:14:06 -04:00
|
|
|
|
expect(Search.execute('status:closed').posts.length).to eq(1)
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(Search.execute('test status:open').posts.length).to eq(0)
|
2014-09-03 07:54:10 -04:00
|
|
|
|
|
|
|
|
|
topic.archived = true
|
|
|
|
|
topic.closed = false
|
|
|
|
|
topic.save
|
|
|
|
|
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(Search.execute('test status:archived').posts.length).to eq(1)
|
|
|
|
|
expect(Search.execute('test status:open').posts.length).to eq(0)
|
2014-10-17 23:54:11 -04:00
|
|
|
|
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(Search.execute('test status:noreplies').posts.length).to eq(1)
|
2014-10-17 23:54:11 -04:00
|
|
|
|
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(Search.execute('test in:likes', guardian: Guardian.new(topic.user)).posts.length).to eq(0)
|
2014-10-18 00:19:08 -04:00
|
|
|
|
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(Search.execute('test in:posted', guardian: Guardian.new(topic.user)).posts.length).to eq(1)
|
2014-10-18 00:19:08 -04:00
|
|
|
|
|
2014-10-18 00:34:05 -04:00
|
|
|
|
TopicUser.change(topic.user.id, topic.id, notification_level: TopicUser.notification_levels[:tracking])
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(Search.execute('test in:watching', guardian: Guardian.new(topic.user)).posts.length).to eq(0)
|
|
|
|
|
expect(Search.execute('test in:tracking', guardian: Guardian.new(topic.user)).posts.length).to eq(1)
|
2014-10-18 00:34:05 -04:00
|
|
|
|
|
2014-09-03 08:10:18 -04:00
|
|
|
|
end
|
|
|
|
|
|
2017-06-06 08:39:53 -04:00
|
|
|
|
it 'can find posts with images' do
|
|
|
|
|
post_uploaded = Fabricate(:post_with_uploaded_image)
|
|
|
|
|
post_with_image_urls = Fabricate(:post_with_image_urls)
|
|
|
|
|
Fabricate(:post)
|
2017-06-07 14:13:36 -04:00
|
|
|
|
|
|
|
|
|
CookedPostProcessor.new(post_uploaded).update_post_image
|
|
|
|
|
CookedPostProcessor.new(post_with_image_urls).update_post_image
|
2017-06-06 08:39:53 -04:00
|
|
|
|
|
2017-06-09 07:16:50 -04:00
|
|
|
|
expect(Search.execute('with:images').posts.map(&:id)).to contain_exactly(post_uploaded.id, post_with_image_urls.id)
|
2017-06-06 08:39:53 -04:00
|
|
|
|
end
|
|
|
|
|
|
2014-09-03 08:10:18 -04:00
|
|
|
|
it 'can find by latest' do
|
|
|
|
|
topic1 = Fabricate(:topic, title: 'I do not like that Sam I am')
|
|
|
|
|
post1 = Fabricate(:post, topic: topic1)
|
|
|
|
|
|
|
|
|
|
post2 = Fabricate(:post, raw: 'that Sam I am, that Sam I am')
|
|
|
|
|
|
2015-04-25 11:18:35 -04:00
|
|
|
|
expect(Search.execute('sam').posts.map(&:id)).to eq([post1.id, post2.id])
|
|
|
|
|
expect(Search.execute('sam order:latest').posts.map(&:id)).to eq([post2.id, post1.id])
|
2017-05-24 11:24:41 -04:00
|
|
|
|
expect(Search.execute('sam l').posts.map(&:id)).to eq([post2.id, post1.id])
|
|
|
|
|
expect(Search.execute('l sam').posts.map(&:id)).to eq([post2.id, post1.id])
|
2017-03-29 13:33:23 -04:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'can order by topic creation' do
|
|
|
|
|
today = Date.today
|
|
|
|
|
yesterday = 1.day.ago
|
|
|
|
|
two_days_ago = 2.days.ago
|
2019-04-01 01:40:11 -04:00
|
|
|
|
category = Fabricate(:category)
|
|
|
|
|
|
|
|
|
|
old_topic = Fabricate(:topic,
|
|
|
|
|
title: 'First Topic, testing the created_at sort',
|
|
|
|
|
created_at: two_days_ago,
|
|
|
|
|
category: category
|
|
|
|
|
)
|
2017-03-29 13:33:23 -04:00
|
|
|
|
|
|
|
|
|
latest_topic = Fabricate(:topic,
|
2019-04-01 01:40:11 -04:00
|
|
|
|
title: 'Second Topic, testing the created_at sort',
|
|
|
|
|
created_at: yesterday,
|
|
|
|
|
category: category
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
old_relevant_topic_post = Fabricate(:post,
|
|
|
|
|
topic: old_topic,
|
|
|
|
|
created_at: yesterday,
|
|
|
|
|
raw: 'Relevant Relevant Topic'
|
|
|
|
|
)
|
2017-03-29 13:33:23 -04:00
|
|
|
|
|
2019-04-01 01:40:11 -04:00
|
|
|
|
latest_irelevant_topic_post = Fabricate(:post,
|
|
|
|
|
topic: latest_topic,
|
|
|
|
|
created_at: today,
|
|
|
|
|
raw: 'Not Relevant'
|
|
|
|
|
)
|
2017-03-29 13:33:23 -04:00
|
|
|
|
|
|
|
|
|
# Expecting the default results
|
2019-04-01 01:40:11 -04:00
|
|
|
|
expect(Search.execute('Topic').posts).to contain_exactly(
|
|
|
|
|
old_relevant_topic_post,
|
|
|
|
|
latest_irelevant_topic_post,
|
|
|
|
|
category.topic.first_post
|
|
|
|
|
)
|
2014-09-03 07:54:10 -04:00
|
|
|
|
|
2017-03-29 13:33:23 -04:00
|
|
|
|
# Expecting the ordered by topic creation results
|
2019-04-01 01:40:11 -04:00
|
|
|
|
expect(Search.execute('Topic order:latest_topic').posts).to contain_exactly(
|
|
|
|
|
latest_irelevant_topic_post,
|
|
|
|
|
old_relevant_topic_post,
|
|
|
|
|
category.topic.first_post
|
|
|
|
|
)
|
2014-09-03 07:54:10 -04:00
|
|
|
|
end
|
2016-05-11 05:53:54 -04:00
|
|
|
|
|
2016-07-25 02:26:33 -04:00
|
|
|
|
it 'can tokenize dots' do
|
|
|
|
|
post = Fabricate(:post, raw: 'Will.2000 Will.Bob.Bill...')
|
|
|
|
|
expect(Search.execute('bill').posts.map(&:id)).to eq([post.id])
|
|
|
|
|
end
|
|
|
|
|
|
2017-08-14 16:19:28 -04:00
|
|
|
|
it 'can tokanize website names correctly' do
|
2017-12-19 00:04:24 -05:00
|
|
|
|
post = Fabricate(:post, raw: 'i like http://wb.camra.org.uk/latest#test so yay')
|
|
|
|
|
expect(Search.execute('http://wb.camra.org.uk/latest#test').posts.map(&:id)).to eq([post.id])
|
|
|
|
|
expect(Search.execute('camra').posts.map(&:id)).to eq([post.id])
|
2017-08-14 16:19:28 -04:00
|
|
|
|
end
|
|
|
|
|
|
2016-06-02 08:41:24 -04:00
|
|
|
|
it 'supports category slug and tags' do
|
2016-05-11 05:53:54 -04:00
|
|
|
|
# main category
|
2019-03-12 02:11:21 -04:00
|
|
|
|
category = Fabricate(:category, name: 'category 24', slug: 'cateGory-24')
|
2016-05-11 05:53:54 -04:00
|
|
|
|
topic = Fabricate(:topic, created_at: 3.months.ago, category: category)
|
2017-02-07 15:53:37 -05:00
|
|
|
|
post = Fabricate(:post, raw: 'Sams first post', topic: topic)
|
2016-05-11 05:53:54 -04:00
|
|
|
|
|
2019-03-12 02:11:21 -04:00
|
|
|
|
expect(Search.execute('sams post #categoRy-24').posts.length).to eq(1)
|
2017-02-07 15:53:37 -05:00
|
|
|
|
expect(Search.execute("sams post category:#{category.id}").posts.length).to eq(1)
|
2019-03-12 02:11:21 -04:00
|
|
|
|
expect(Search.execute('sams post #categoRy-25').posts.length).to eq(0)
|
2016-05-11 05:53:54 -04:00
|
|
|
|
|
|
|
|
|
sub_category = Fabricate(:category, name: 'sub category', slug: 'sub-category', parent_category_id: category.id)
|
|
|
|
|
second_topic = Fabricate(:topic, created_at: 3.months.ago, category: sub_category)
|
2017-02-07 15:53:37 -05:00
|
|
|
|
Fabricate(:post, raw: 'sams second post', topic: second_topic)
|
2016-05-11 05:53:54 -04:00
|
|
|
|
|
2019-03-12 02:11:21 -04:00
|
|
|
|
expect(Search.execute("sams post category:categoRY-24").posts.length).to eq(2)
|
|
|
|
|
expect(Search.execute("sams post category:=cAtegory-24").posts.length).to eq(1)
|
2017-02-07 15:53:37 -05:00
|
|
|
|
|
|
|
|
|
expect(Search.execute("sams post #category-24").posts.length).to eq(2)
|
|
|
|
|
expect(Search.execute("sams post #=category-24").posts.length).to eq(1)
|
|
|
|
|
expect(Search.execute("sams post #sub-category").posts.length).to eq(1)
|
2016-06-02 08:41:24 -04:00
|
|
|
|
|
2019-03-12 02:11:21 -04:00
|
|
|
|
expect(Search.execute("sams post #categoRY-24:SUB-category").posts.length)
|
|
|
|
|
.to eq(1)
|
|
|
|
|
|
2016-06-02 08:41:24 -04:00
|
|
|
|
# tags
|
2018-10-05 05:23:52 -04:00
|
|
|
|
topic.tags = [Fabricate(:tag, name: 'alpha'), Fabricate(:tag, name: 'привет'), Fabricate(:tag, name: 'HeLlO')]
|
2016-06-02 08:41:24 -04:00
|
|
|
|
expect(Search.execute('this is a test #alpha').posts.map(&:id)).to eq([post.id])
|
2018-08-26 21:05:28 -04:00
|
|
|
|
expect(Search.execute('this is a test #привет').posts.map(&:id)).to eq([post.id])
|
2018-10-05 05:23:52 -04:00
|
|
|
|
expect(Search.execute('this is a test #hElLo').posts.map(&:id)).to eq([post.id])
|
2016-06-02 08:41:24 -04:00
|
|
|
|
expect(Search.execute('this is a test #beta').posts.size).to eq(0)
|
2016-05-11 05:53:54 -04:00
|
|
|
|
end
|
2016-05-04 14:02:47 -04:00
|
|
|
|
|
2017-08-01 18:15:04 -04:00
|
|
|
|
it 'correctly handles #symbol when no tag or category match' do
|
|
|
|
|
Fabricate(:post, raw: 'testing #1 #9998')
|
|
|
|
|
results = Search.new('testing #1').execute
|
|
|
|
|
expect(results.posts.length).to eq(1)
|
|
|
|
|
|
|
|
|
|
results = Search.new('#9998').execute
|
|
|
|
|
expect(results.posts.length).to eq(1)
|
|
|
|
|
|
|
|
|
|
results = Search.new('#777').execute
|
|
|
|
|
expect(results.posts.length).to eq(0)
|
2018-05-28 01:28:02 -04:00
|
|
|
|
|
|
|
|
|
results = Search.new('xxx #:').execute
|
|
|
|
|
expect(results.posts.length).to eq(0)
|
2017-08-01 18:15:04 -04:00
|
|
|
|
end
|
|
|
|
|
|
2017-05-30 07:01:17 -04:00
|
|
|
|
context 'tags' do
|
|
|
|
|
let(:tag1) { Fabricate(:tag, name: 'lunch') }
|
|
|
|
|
let(:tag2) { Fabricate(:tag, name: 'eggs') }
|
2018-01-03 16:45:21 -05:00
|
|
|
|
let(:tag3) { Fabricate(:tag, name: 'sandwiches') }
|
2017-05-30 07:01:17 -04:00
|
|
|
|
let(:topic1) { Fabricate(:topic, tags: [tag2, Fabricate(:tag)]) }
|
2017-05-31 11:32:29 -04:00
|
|
|
|
let(:topic2) { Fabricate(:topic, tags: [tag2]) }
|
2017-05-30 07:01:17 -04:00
|
|
|
|
let(:topic3) { Fabricate(:topic, tags: [tag1, tag2]) }
|
2018-01-03 16:45:21 -05:00
|
|
|
|
let(:topic4) { Fabricate(:topic, tags: [tag1, tag2, tag3]) }
|
|
|
|
|
let(:topic5) { Fabricate(:topic, tags: [tag2, tag3]) }
|
2017-07-27 21:20:09 -04:00
|
|
|
|
let!(:post1) { Fabricate(:post, topic: topic1) }
|
|
|
|
|
let!(:post2) { Fabricate(:post, topic: topic2) }
|
|
|
|
|
let!(:post3) { Fabricate(:post, topic: topic3) }
|
2018-01-03 16:45:21 -05:00
|
|
|
|
let!(:post4) { Fabricate(:post, topic: topic4) }
|
|
|
|
|
let!(:post5) { Fabricate(:post, topic: topic5) }
|
2017-05-30 07:01:17 -04:00
|
|
|
|
|
2017-05-31 11:32:29 -04:00
|
|
|
|
it 'can find posts with tag' do
|
|
|
|
|
post4 = Fabricate(:post, topic: topic3, raw: "It probably doesn't help that they're green...")
|
|
|
|
|
|
|
|
|
|
expect(Search.execute('green tags:eggs').posts.map(&:id)).to eq([post4.id])
|
|
|
|
|
expect(Search.execute('tags:plants').posts.size).to eq(0)
|
|
|
|
|
end
|
|
|
|
|
|
2018-08-26 21:05:28 -04:00
|
|
|
|
it 'can find posts with non-latin tag' do
|
|
|
|
|
topic = Fabricate(:topic)
|
|
|
|
|
topic.tags = [Fabricate(:tag, name: 'さようなら')]
|
|
|
|
|
post = Fabricate(:post, raw: 'Testing post', topic: topic)
|
|
|
|
|
|
|
|
|
|
expect(Search.execute('tags:さようなら').posts.map(&:id)).to eq([post.id])
|
|
|
|
|
end
|
|
|
|
|
|
2017-05-30 07:01:17 -04:00
|
|
|
|
it 'can find posts with any tag from multiple tags' do
|
|
|
|
|
Fabricate(:post)
|
|
|
|
|
|
2018-01-03 16:45:21 -05:00
|
|
|
|
expect(Search.execute('tags:eggs,lunch').posts.map(&:id).sort).to eq([post1.id, post2.id, post3.id, post4.id, post5.id].sort)
|
2017-05-30 07:01:17 -04:00
|
|
|
|
end
|
2016-05-04 14:02:47 -04:00
|
|
|
|
|
2017-05-30 07:01:17 -04:00
|
|
|
|
it 'can find posts which contains all provided tags' do
|
2018-01-03 16:45:21 -05:00
|
|
|
|
expect(Search.execute('tags:lunch+eggs+sandwiches').posts.map(&:id)).to eq([post4.id].sort)
|
|
|
|
|
expect(Search.execute('tags:eggs+lunch+sandwiches').posts.map(&:id)).to eq([post4.id].sort)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'can find posts which contains provided tags and does not contain selected ones' do
|
|
|
|
|
expect(Search.execute('tags:eggs -tags:lunch').posts)
|
|
|
|
|
.to contain_exactly(post1, post2, post5)
|
|
|
|
|
|
|
|
|
|
expect(Search.execute('tags:eggs -tags:lunch+sandwiches').posts)
|
|
|
|
|
.to contain_exactly(post1, post2, post3, post5)
|
|
|
|
|
|
|
|
|
|
expect(Search.execute('tags:eggs -tags:lunch,sandwiches').posts)
|
|
|
|
|
.to contain_exactly(post1, post2)
|
2017-05-30 07:01:17 -04:00
|
|
|
|
end
|
2018-09-28 05:27:08 -04:00
|
|
|
|
|
|
|
|
|
it 'orders posts correctly when combining tags with categories or terms' do
|
|
|
|
|
cat1 = Fabricate(:category, name: 'food')
|
|
|
|
|
topic6 = Fabricate(:topic, tags: [tag1, tag2], category: cat1)
|
|
|
|
|
topic7 = Fabricate(:topic, tags: [tag1, tag2, tag3], category: cat1)
|
|
|
|
|
post7 = Fabricate(:post, topic: topic6, raw: "Wakey, wakey, eggs and bakey.", like_count: 5)
|
|
|
|
|
post8 = Fabricate(:post, topic: topic7, raw: "Bakey, bakey, eggs to makey.", like_count: 2)
|
|
|
|
|
|
|
|
|
|
expect(Search.execute('bakey tags:lunch order:latest').posts.map(&:id))
|
|
|
|
|
.to eq([post8.id, post7.id])
|
|
|
|
|
expect(Search.execute('#food tags:lunch order:latest').posts.map(&:id))
|
|
|
|
|
.to eq([post8.id, post7.id])
|
|
|
|
|
expect(Search.execute('#food tags:lunch order:likes').posts.map(&:id))
|
|
|
|
|
.to eq([post7.id, post8.id])
|
|
|
|
|
end
|
|
|
|
|
|
2016-05-04 14:02:47 -04:00
|
|
|
|
end
|
2017-05-30 07:01:17 -04:00
|
|
|
|
|
2017-06-20 15:21:56 -04:00
|
|
|
|
it "can find posts which contains filetypes" do
|
|
|
|
|
post1 = Fabricate(:post,
|
2017-07-06 13:11:32 -04:00
|
|
|
|
raw: "http://example.com/image.png")
|
2017-06-20 15:21:56 -04:00
|
|
|
|
post2 = Fabricate(:post,
|
|
|
|
|
raw: "Discourse logo\n"\
|
2017-07-06 13:11:32 -04:00
|
|
|
|
"http://example.com/logo.png\n"\
|
|
|
|
|
"http://example.com/vector_image.svg")
|
|
|
|
|
post_with_upload = Fabricate(:post, uploads: [Fabricate(:upload)])
|
2017-06-20 15:21:56 -04:00
|
|
|
|
Fabricate(:post)
|
|
|
|
|
|
|
|
|
|
TopicLink.extract_from(post1)
|
|
|
|
|
TopicLink.extract_from(post2)
|
|
|
|
|
|
2017-07-06 13:11:32 -04:00
|
|
|
|
expect(Search.execute('filetype:svg').posts).to eq([post2])
|
2017-07-03 13:08:59 -04:00
|
|
|
|
expect(Search.execute('filetype:png').posts.map(&:id)).to contain_exactly(post1.id, post2.id, post_with_upload.id)
|
|
|
|
|
expect(Search.execute('logo filetype:png').posts.map(&:id)).to eq([post2.id])
|
2017-06-20 15:21:56 -04:00
|
|
|
|
end
|
2014-09-03 07:54:10 -04:00
|
|
|
|
end
|
|
|
|
|
|
2018-11-21 16:07:13 -05:00
|
|
|
|
context '#ts_query' do
|
|
|
|
|
it 'can parse complex strings using ts_query helper' do
|
|
|
|
|
str = " grigio:babel deprecated? "
|
|
|
|
|
str << "page page on Atmosphere](https://atmospherejs.com/grigio/babel)xxx: aaa.js:222 aaa'\"bbb"
|
2015-08-13 03:55:10 -04:00
|
|
|
|
|
2018-11-21 16:07:13 -05:00
|
|
|
|
ts_query = Search.ts_query(term: str, ts_config: "simple")
|
|
|
|
|
expect { DB.exec("SELECT to_tsvector('bbb') @@ " << ts_query) }.to_not raise_error
|
|
|
|
|
|
|
|
|
|
ts_query = Search.ts_query(term: "foo.bar/'&baz", ts_config: "simple")
|
|
|
|
|
expect { DB.exec("SELECT to_tsvector('bbb') @@ " << ts_query) }.to_not raise_error
|
|
|
|
|
expect(ts_query).to include("baz")
|
|
|
|
|
end
|
2015-08-13 03:55:10 -04:00
|
|
|
|
end
|
|
|
|
|
|
2016-03-14 08:27:02 -04:00
|
|
|
|
context '#word_to_date' do
|
|
|
|
|
it 'parses relative dates correctly' do
|
|
|
|
|
time = Time.zone.parse('2001-02-20 2:55')
|
|
|
|
|
freeze_time(time)
|
|
|
|
|
|
|
|
|
|
expect(Search.word_to_date('yesterday')).to eq(time.beginning_of_day.yesterday)
|
|
|
|
|
expect(Search.word_to_date('suNday')).to eq(Time.zone.parse('2001-02-18'))
|
|
|
|
|
expect(Search.word_to_date('thursday')).to eq(Time.zone.parse('2001-02-15'))
|
|
|
|
|
expect(Search.word_to_date('deCember')).to eq(Time.zone.parse('2000-12-01'))
|
|
|
|
|
expect(Search.word_to_date('deC')).to eq(Time.zone.parse('2000-12-01'))
|
|
|
|
|
expect(Search.word_to_date('january')).to eq(Time.zone.parse('2001-01-01'))
|
|
|
|
|
expect(Search.word_to_date('jan')).to eq(Time.zone.parse('2001-01-01'))
|
|
|
|
|
|
|
|
|
|
expect(Search.word_to_date('100')).to eq(time.beginning_of_day.days_ago(100))
|
|
|
|
|
|
|
|
|
|
expect(Search.word_to_date('invalid')).to eq(nil)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'parses absolute dates correctly' do
|
|
|
|
|
expect(Search.word_to_date('2001-1-20')).to eq(Time.zone.parse('2001-01-20'))
|
|
|
|
|
expect(Search.word_to_date('2030-10-2')).to eq(Time.zone.parse('2030-10-02'))
|
|
|
|
|
expect(Search.word_to_date('2030-10')).to eq(Time.zone.parse('2030-10-01'))
|
|
|
|
|
expect(Search.word_to_date('2030')).to eq(Time.zone.parse('2030-01-01'))
|
|
|
|
|
expect(Search.word_to_date('2030-01-32')).to eq(nil)
|
|
|
|
|
expect(Search.word_to_date('10000')).to eq(nil)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2016-08-10 15:40:58 -04:00
|
|
|
|
context "#min_post_id" do
|
|
|
|
|
it "returns 0 when prefer_recent_posts is disabled" do
|
|
|
|
|
SiteSetting.search_prefer_recent_posts = false
|
|
|
|
|
expect(Search.min_post_id_no_cache).to eq(0)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it "returns a value when prefer_recent_posts is enabled" do
|
|
|
|
|
SiteSetting.search_prefer_recent_posts = true
|
|
|
|
|
SiteSetting.search_recent_posts_size = 1
|
|
|
|
|
|
|
|
|
|
Fabricate(:post)
|
|
|
|
|
p2 = Fabricate(:post)
|
|
|
|
|
|
|
|
|
|
expect(Search.min_post_id_no_cache).to eq(p2.id)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2017-07-17 11:57:13 -04:00
|
|
|
|
context "search_log_id" do
|
|
|
|
|
it "returns an id when the search succeeds" do
|
|
|
|
|
s = Search.new(
|
|
|
|
|
'indiana jones',
|
|
|
|
|
search_type: :header,
|
|
|
|
|
ip_address: '127.0.0.1'
|
|
|
|
|
)
|
|
|
|
|
results = s.execute
|
|
|
|
|
expect(results.search_log_id).to be_present
|
|
|
|
|
end
|
2018-01-16 05:29:22 -05:00
|
|
|
|
|
|
|
|
|
it "does not log search if search_type is not present" do
|
2018-01-17 02:27:33 -05:00
|
|
|
|
s = Search.new('foo bar', ip_address: '127.0.0.1')
|
2018-01-16 05:29:22 -05:00
|
|
|
|
results = s.execute
|
|
|
|
|
expect(results.search_log_id).not_to be_present
|
|
|
|
|
end
|
2017-07-17 11:57:13 -04:00
|
|
|
|
end
|
|
|
|
|
|
2018-02-19 22:41:00 -05:00
|
|
|
|
context 'in:title' do
|
|
|
|
|
it 'allows for search in title' do
|
|
|
|
|
topic = Fabricate(:topic, title: 'I am testing a title search')
|
2018-06-05 03:29:17 -04:00
|
|
|
|
_post = Fabricate(:post, topic: topic, raw: 'this is the first post')
|
2018-02-19 22:41:00 -05:00
|
|
|
|
|
|
|
|
|
results = Search.execute('title in:title')
|
|
|
|
|
expect(results.posts.length).to eq(1)
|
|
|
|
|
|
2019-02-24 18:55:24 -05:00
|
|
|
|
results = Search.execute('title t')
|
|
|
|
|
expect(results.posts.length).to eq(1)
|
|
|
|
|
|
2018-02-19 22:41:00 -05:00
|
|
|
|
results = Search.execute('first in:title')
|
|
|
|
|
expect(results.posts.length).to eq(0)
|
2019-02-24 18:55:24 -05:00
|
|
|
|
|
|
|
|
|
results = Search.execute('first t')
|
|
|
|
|
expect(results.posts.length).to eq(0)
|
2018-02-19 22:41:00 -05:00
|
|
|
|
end
|
2019-02-05 04:54:52 -05:00
|
|
|
|
|
|
|
|
|
it 'works irrespective of the order' do
|
|
|
|
|
topic = Fabricate(:topic, title: "A topic about Discourse")
|
|
|
|
|
Fabricate(:post, topic: topic, raw: "This is another post")
|
|
|
|
|
topic2 = Fabricate(:topic, title: "This is another topic")
|
|
|
|
|
Fabricate(:post, topic: topic2, raw: "Discourse is awesome")
|
|
|
|
|
|
|
|
|
|
results = Search.execute('Discourse in:title status:open')
|
|
|
|
|
expect(results.posts.length).to eq(1)
|
|
|
|
|
|
|
|
|
|
results = Search.execute('in:title status:open Discourse')
|
|
|
|
|
expect(results.posts.length).to eq(1)
|
|
|
|
|
end
|
2018-02-19 22:41:00 -05:00
|
|
|
|
end
|
|
|
|
|
|
2018-10-22 21:10:33 -04:00
|
|
|
|
context 'ignore_diacritics' do
|
|
|
|
|
before { SiteSetting.search_ignore_accents = true }
|
|
|
|
|
let!(:post1) { Fabricate(:post, raw: 'สวัสดี Rágis hello') }
|
|
|
|
|
|
|
|
|
|
it ('allows strips correctly') do
|
|
|
|
|
results = Search.execute('hello', type_filter: 'topic')
|
|
|
|
|
expect(results.posts.length).to eq(1)
|
|
|
|
|
|
|
|
|
|
results = Search.execute('ragis', type_filter: 'topic')
|
|
|
|
|
expect(results.posts.length).to eq(1)
|
|
|
|
|
|
|
|
|
|
results = Search.execute('Rágis', type_filter: 'topic', include_blurbs: true)
|
|
|
|
|
expect(results.posts.length).to eq(1)
|
|
|
|
|
|
|
|
|
|
# TODO: this is a test we need to fix!
|
|
|
|
|
#expect(results.blurb(results.posts.first)).to include('Rágis')
|
|
|
|
|
|
|
|
|
|
results = Search.execute('สวัสดี', type_filter: 'topic')
|
|
|
|
|
expect(results.posts.length).to eq(1)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'include_diacritics' do
|
|
|
|
|
before { SiteSetting.search_ignore_accents = false }
|
2018-08-23 20:00:51 -04:00
|
|
|
|
let!(:post1) { Fabricate(:post, raw: 'สวัสดี Régis hello') }
|
|
|
|
|
|
|
|
|
|
it ('allows strips correctly') do
|
|
|
|
|
results = Search.execute('hello', type_filter: 'topic')
|
|
|
|
|
expect(results.posts.length).to eq(1)
|
|
|
|
|
|
|
|
|
|
results = Search.execute('regis', type_filter: 'topic')
|
2018-08-30 21:46:55 -04:00
|
|
|
|
expect(results.posts.length).to eq(0)
|
2018-08-23 20:00:51 -04:00
|
|
|
|
|
2018-08-30 21:46:55 -04:00
|
|
|
|
results = Search.execute('Régis', type_filter: 'topic', include_blurbs: true)
|
2018-08-23 20:00:51 -04:00
|
|
|
|
expect(results.posts.length).to eq(1)
|
|
|
|
|
|
2018-08-30 21:46:55 -04:00
|
|
|
|
expect(results.blurb(results.posts.first)).to include('Régis')
|
|
|
|
|
|
2018-08-23 20:00:51 -04:00
|
|
|
|
results = Search.execute('สวัสดี', type_filter: 'topic')
|
|
|
|
|
expect(results.posts.length).to eq(1)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2017-07-21 04:43:02 -04:00
|
|
|
|
context 'pagination' do
|
|
|
|
|
let(:number_of_results) { 2 }
|
2017-07-31 20:34:02 -04:00
|
|
|
|
let!(:post1) { Fabricate(:post, raw: 'hello hello hello hello hello') }
|
|
|
|
|
let!(:post2) { Fabricate(:post, raw: 'hello hello hello hello') }
|
|
|
|
|
let!(:post3) { Fabricate(:post, raw: 'hello hello hello') }
|
|
|
|
|
let!(:post4) { Fabricate(:post, raw: 'hello hello') }
|
|
|
|
|
let!(:post5) { Fabricate(:post, raw: 'hello') }
|
2017-07-21 04:43:02 -04:00
|
|
|
|
before do
|
|
|
|
|
Search.stubs(:per_filter).returns(number_of_results)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'returns more results flag' do
|
|
|
|
|
results = Search.execute('hello', type_filter: 'topic')
|
|
|
|
|
results2 = Search.execute('hello', type_filter: 'topic', page: 2)
|
|
|
|
|
|
|
|
|
|
expect(results.posts.length).to eq(number_of_results)
|
2017-07-26 06:10:19 -04:00
|
|
|
|
expect(results.posts.map(&:id)).to eq([post1.id, post2.id])
|
2017-07-21 04:43:02 -04:00
|
|
|
|
expect(results.more_full_page_results).to eq(true)
|
|
|
|
|
expect(results2.posts.length).to eq(number_of_results)
|
2017-07-26 06:10:19 -04:00
|
|
|
|
expect(results2.posts.map(&:id)).to eq([post3.id, post4.id])
|
2017-07-21 04:43:02 -04:00
|
|
|
|
expect(results2.more_full_page_results).to eq(true)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'correctly search with page parameter' do
|
|
|
|
|
search = Search.new('hello', type_filter: 'topic', page: 3)
|
|
|
|
|
results = search.execute
|
|
|
|
|
|
|
|
|
|
expect(search.offset).to eq(2 * number_of_results)
|
|
|
|
|
expect(results.posts.length).to eq(1)
|
2017-07-26 06:10:19 -04:00
|
|
|
|
expect(results.posts).to eq([post5])
|
2017-07-21 04:43:02 -04:00
|
|
|
|
expect(results.more_full_page_results).to eq(nil)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
2013-02-05 14:16:51 -05:00
|
|
|
|
end
|