321 lines
9 KiB
Ruby
321 lines
9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'rails_helper'
|
|
|
|
RSpec.describe StatusesSearchService do
|
|
describe 'a local user posts with searchability' do
|
|
subject do
|
|
described_class.new.call('ohagi', account, limit: 10, searchability: searchability).map(&:id)
|
|
end
|
|
|
|
let(:alice) { Fabricate(:user).account }
|
|
let(:following) { Fabricate(:user).account }
|
|
let(:reacted) { Fabricate(:user).account }
|
|
let(:other) { Fabricate(:user).account }
|
|
let(:account) { nil }
|
|
let(:searchability) { :public }
|
|
let!(:status) { Fabricate(:status, text: 'Hello, ohagi', account: alice, searchability: searchability) }
|
|
|
|
before do
|
|
alice.update!(indexable: true)
|
|
following.follow!(alice)
|
|
Fabricate(:favourite, account: reacted, status: status)
|
|
PublicStatusesIndex.import!
|
|
StatusesIndex.import!
|
|
end
|
|
|
|
context 'when public searchability' do
|
|
let(:searchability) { :public }
|
|
let(:account) { other }
|
|
|
|
context 'with other account' do
|
|
it 'search status' do
|
|
expect(subject.count).to eq 1
|
|
expect(subject).to include status.id
|
|
end
|
|
end
|
|
|
|
context 'with follower' do
|
|
let(:account) { following }
|
|
|
|
it 'search status' do
|
|
expect(subject.count).to eq 1
|
|
expect(subject).to include status.id
|
|
end
|
|
end
|
|
|
|
context 'with reacted user' do
|
|
let(:account) { reacted }
|
|
|
|
it 'search status' do
|
|
expect(subject.count).to eq 1
|
|
expect(subject).to include status.id
|
|
end
|
|
end
|
|
|
|
context 'with self' do
|
|
let(:account) { alice }
|
|
|
|
it 'search status' do
|
|
expect(subject.count).to eq 1
|
|
expect(subject).to include status.id
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'when public_unlisted searchability' do
|
|
let(:searchability) { :public_unlisted }
|
|
let(:account) { other }
|
|
|
|
context 'with other account' do
|
|
it 'search status' do
|
|
expect(subject.count).to eq 1
|
|
expect(subject).to include status.id
|
|
end
|
|
end
|
|
|
|
context 'with follower' do
|
|
let(:account) { following }
|
|
|
|
it 'search status' do
|
|
expect(subject.count).to eq 1
|
|
expect(subject).to include status.id
|
|
end
|
|
end
|
|
|
|
context 'with reacted user' do
|
|
let(:account) { reacted }
|
|
|
|
it 'search status' do
|
|
expect(subject.count).to eq 1
|
|
expect(subject).to include status.id
|
|
end
|
|
end
|
|
|
|
context 'with self' do
|
|
let(:account) { alice }
|
|
|
|
it 'search status' do
|
|
expect(subject.count).to eq 1
|
|
expect(subject).to include status.id
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'when private searchability' do
|
|
let(:searchability) { :private }
|
|
let(:account) { other }
|
|
|
|
context 'with other account' do
|
|
it 'search status' do
|
|
expect(subject.count).to eq 0
|
|
end
|
|
end
|
|
|
|
context 'with follower' do
|
|
let(:account) { following }
|
|
|
|
it 'search status' do
|
|
expect(subject.count).to eq 1
|
|
expect(subject).to include status.id
|
|
end
|
|
end
|
|
|
|
context 'with reacted user' do
|
|
let(:account) { reacted }
|
|
|
|
it 'search status' do
|
|
expect(subject.count).to eq 1
|
|
expect(subject).to include status.id
|
|
end
|
|
end
|
|
|
|
context 'with self' do
|
|
let(:account) { alice }
|
|
|
|
it 'search status' do
|
|
expect(subject.count).to eq 1
|
|
expect(subject).to include status.id
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'when direct searchability' do
|
|
let(:searchability) { :direct }
|
|
let(:account) { other }
|
|
|
|
context 'with other account' do
|
|
it 'search status' do
|
|
expect(subject.count).to eq 0
|
|
end
|
|
end
|
|
|
|
context 'with follower' do
|
|
let(:account) { following }
|
|
|
|
it 'search status' do
|
|
expect(subject.count).to eq 0
|
|
end
|
|
end
|
|
|
|
context 'with reacted user' do
|
|
let(:account) { reacted }
|
|
|
|
it 'search status' do
|
|
expect(subject.count).to eq 1
|
|
expect(subject).to include status.id
|
|
end
|
|
end
|
|
|
|
context 'with self' do
|
|
let(:account) { alice }
|
|
|
|
it 'search status' do
|
|
expect(subject.count).to eq 1
|
|
expect(subject).to include status.id
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'when limited searchability' do
|
|
let(:searchability) { :limited }
|
|
let(:account) { other }
|
|
|
|
context 'with other account' do
|
|
it 'search status' do
|
|
expect(subject.count).to eq 0
|
|
end
|
|
end
|
|
|
|
context 'with follower' do
|
|
let(:account) { following }
|
|
|
|
it 'search status' do
|
|
expect(subject.count).to eq 0
|
|
end
|
|
end
|
|
|
|
context 'with reacted user' do
|
|
let(:account) { reacted }
|
|
|
|
it 'search status' do
|
|
expect(subject.count).to eq 0
|
|
end
|
|
end
|
|
|
|
context 'with self' do
|
|
let(:account) { alice }
|
|
|
|
it 'search status' do
|
|
expect(subject.count).to eq 1
|
|
expect(subject).to include status.id
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'a local user posts with search keyword' do
|
|
subject do
|
|
described_class.new.call(search_keyword, account, limit: 10).map(&:id)
|
|
end
|
|
|
|
let(:search_keyword) { 'ohagi' }
|
|
let(:status_text) { 'I ate an apple.' }
|
|
let(:searchability) { :public }
|
|
|
|
let(:alice) { Fabricate(:user).account }
|
|
let(:account) { alice }
|
|
let!(:status) { Fabricate(:status, text: status_text, account: alice, searchability: searchability) }
|
|
|
|
before do
|
|
alice.update!(username: 'alice')
|
|
StatusesIndex.import!
|
|
PublicStatusesIndex.import!
|
|
end
|
|
|
|
shared_examples 'hit status' do |name, keyword|
|
|
context name do
|
|
let(:search_keyword) { keyword }
|
|
|
|
it 'a status hits' do
|
|
expect(subject.count).to eq 1
|
|
expect(subject).to include status.id
|
|
end
|
|
end
|
|
end
|
|
|
|
shared_examples 'does not hit status' do |name, keyword|
|
|
context name do
|
|
let(:search_keyword) { keyword }
|
|
|
|
it 'no statuses hit' do
|
|
expect(subject.count).to eq 0
|
|
end
|
|
end
|
|
end
|
|
|
|
it_behaves_like 'hit status', 'when search with word', 'apple'
|
|
it_behaves_like 'hit status', 'when search with multiple words', 'apple ate'
|
|
it_behaves_like 'does not hit status', 'when search with multiple words but does not hit half', 'apple kill'
|
|
# it_behaves_like 'hit status', 'when search with letter in word', 'p' # available only Japanese sudachi
|
|
# it_behaves_like 'does not hit status', 'when double quote search with letter in word', '"p"' # available only Japanese sudachi
|
|
it_behaves_like 'hit status', 'when search with fixed word', '"apple"'
|
|
# it_behaves_like 'hit status', 'when double quote search with multiple letter in word', 'p e' # available only Japanese sudachi
|
|
it_behaves_like 'does not hit status', 'when double quote search with multiple letter in word but does not contain half', 'q p'
|
|
it_behaves_like 'hit status', 'when specify user name', 'apple from:alice'
|
|
it_behaves_like 'does not hit status', 'when specify not existing user name', 'apple from:ohagi'
|
|
|
|
context 'when indexable is enabled' do
|
|
let(:account) { Fabricate(:user).account }
|
|
let(:alice) { Fabricate(:user, account: Fabricate(:account, indexable: true)).account }
|
|
let(:searchability) { nil }
|
|
|
|
it_behaves_like 'hit status', 'when scope is all statuses', 'apple'
|
|
it_behaves_like 'does not hit status', 'when in:library is specified', 'apple in:library'
|
|
it_behaves_like 'hit status', 'when in:public is specified', 'apple in:public'
|
|
|
|
context 'with public searchability' do
|
|
let(:searchability) { :public }
|
|
|
|
it_behaves_like 'hit status', 'when scope is all public_searchability statuses', 'apple in:library'
|
|
end
|
|
end
|
|
|
|
context 'when in:following is specified' do
|
|
let(:following) { Fabricate(:user).account }
|
|
let(:other) { Fabricate(:user).account }
|
|
|
|
before do
|
|
following.follow!(alice)
|
|
end
|
|
|
|
context 'with myself' do
|
|
let(:account) { alice }
|
|
|
|
it_behaves_like 'does not hit status', 'when search with following', 'in:following apple'
|
|
end
|
|
|
|
context 'with following' do
|
|
let(:account) { following }
|
|
|
|
it_behaves_like 'hit status', 'when search with following', 'in:following apple'
|
|
end
|
|
|
|
context 'without following' do
|
|
let(:account) { other }
|
|
|
|
it_behaves_like 'does not hit status', 'when search with following', 'in:following apple'
|
|
end
|
|
end
|
|
|
|
context 'when reverse_search_quote is enabled' do
|
|
before do
|
|
alice.user.update!(settings: { reverse_search_quote: true })
|
|
end
|
|
|
|
it_behaves_like 'does not hit status', 'when search with letter in word', 'p'
|
|
# it_behaves_like 'hit status', 'when double quote search with letter in word', '"p"' # available only Japanese sudachi
|
|
it_behaves_like 'hit status', 'when search with word', 'apple'
|
|
end
|
|
end
|
|
end
|