about summary refs log tree commit diff
path: root/spec/services/account_search_service_spec.rb
blob: c5ddc5844a32d365fdb4f8ae6e7fb054c8772fda (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
require 'rails_helper'

describe AccountSearchService do
  describe '.call' do
    describe 'with a query to ignore' do
      it 'returns empty array for missing query' do
        results = subject.call('', 10)

        expect(results).to eq []
      end
      it 'returns empty array for hashtag query' do
        results = subject.call('#tag', 10)

        expect(results).to eq []
      end
      it 'returns empty array for limit zero' do
        Fabricate(:account, username: 'match')
        results = subject.call('match', 0)

        expect(results).to eq []
      end
    end

    describe 'searching for a simple term that is not an exact match' do
      it 'does not return a nil entry in the array for the exact match' do
        match = Fabricate(:account, username: 'matchingusername')

        results = subject.call('match', 5)
        expect(results).to eq [match]
      end
    end

    describe 'searching local and remote users' do
      describe "when only '@'" do
        before do
          allow(Account).to receive(:find_local)
          allow(Account).to receive(:search_for)
          subject.call('@', 10)
        end

        it 'uses find_local with empty query to look for local accounts' do
          expect(Account).to have_received(:find_local).with('')
        end
      end

      describe 'when no domain' do
        before do
          allow(Account).to receive(:find_local)
          allow(Account).to receive(:search_for)
          subject.call('one', 10)
        end

        it 'uses find_local to look for local accounts' do
          expect(Account).to have_received(:find_local).with('one')
        end

        it 'uses search_for to find matches' do
          expect(Account).to have_received(:search_for).with('one', 10)
        end
      end

      describe 'when there is a domain' do
        before do
          allow(Account).to receive(:find_remote)
        end

        it 'uses find_remote to look for remote accounts' do
          subject.call('two@example.com', 10)
          expect(Account).to have_received(:find_remote).with('two', 'example.com')
        end

        describe 'and there is no account provided' do
          it 'uses search_for to find matches' do
            allow(Account).to receive(:search_for)
            subject.call('two@example.com', 10, nil, resolve: false)

            expect(Account).to have_received(:search_for).with('two example.com', 10)
          end
        end

        describe 'and there is an account provided' do
          it 'uses advanced_search_for to find matches' do
            account = Fabricate(:account)
            allow(Account).to receive(:advanced_search_for)
            subject.call('two@example.com', 10, account, resolve: false)

            expect(Account).to have_received(:advanced_search_for).with('two example.com', account, 10, nil)
          end
        end
      end
    end

    describe 'with an exact match' do
      it 'returns exact match first, and does not return duplicates' do
        partial = Fabricate(:account, username: 'exactness')
        exact = Fabricate(:account, username: 'exact')

        results = subject.call('exact', 10)
        expect(results.size).to eq 2
        expect(results).to eq [exact, partial]
      end
    end

    describe 'when there is a local domain' do
      around do |example|
        before = Rails.configuration.x.local_domain
        example.run
        Rails.configuration.x.local_domain = before
      end

      it 'returns exact match first' do
        remote     = Fabricate(:account, username: 'a', domain: 'remote', display_name: 'e')
        remote_too = Fabricate(:account, username: 'b', domain: 'remote', display_name: 'e')
        exact = Fabricate(:account, username: 'e')
        Rails.configuration.x.local_domain = 'example.com'

        results = subject.call('e@example.com', 2)
        expect(results.size).to eq 2
        expect(results).to eq([exact, remote]).or eq([exact, remote_too])
      end
    end

    describe 'when there is a domain but no exact match' do
      it 'follows the remote account when resolve is true' do
        service = double(call: nil)
        allow(ResolveAccountService).to receive(:new).and_return(service)

        results = subject.call('newuser@remote.com', 10, nil, resolve: true)
        expect(service).to have_received(:call).with('newuser@remote.com')
      end

      it 'does not follow the remote account when resolve is false' do
        service = double(call: nil)
        allow(ResolveAccountService).to receive(:new).and_return(service)

        results = subject.call('newuser@remote.com', 10, nil, resolve: false)
        expect(service).not_to have_received(:call)
      end
    end

    describe 'should not include suspended accounts' do
      it 'returns the fuzzy match first, and does not return suspended exacts' do
        partial = Fabricate(:account, username: 'exactness')
        exact = Fabricate(:account, username: 'exact', suspended: true)

        results = subject.call('exact', 10)
        expect(results.size).to eq 1
        expect(results).to eq [partial]
      end

      it "does not return suspended remote accounts" do
        remote = Fabricate(:account, username: 'a', domain: 'remote', display_name: 'e', suspended: true)

        results = subject.call('a@example.com', 2)
        expect(results.size).to eq 0
        expect(results).to eq []
      end
    end
  end
end