elastic-app-search 7.4.0 → 7.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,11 +7,19 @@ module Elastic
7
7
  module AppSearch
8
8
  # API client for the {Elastic App Search API}[https://www.elastic.co/cloud/app-search-service].
9
9
  class Client
10
+ autoload :Analytics, 'elastic/app-search/client/analytics'
11
+ autoload :Click, 'elastic/app-search/client/click'
12
+ autoload :Credentials, 'elastic/app-search/client/credentials'
13
+ autoload :Curations, 'elastic/app-search/client/curations'
10
14
  autoload :Documents, 'elastic/app-search/client/documents'
11
15
  autoload :Engines, 'elastic/app-search/client/engines'
16
+ autoload :MetaEngines, 'elastic/app-search/client/meta_engines'
17
+ autoload :Logs, 'elastic/app-search/client/logs'
18
+ autoload :Schema, 'elastic/app-search/client/schema'
12
19
  autoload :Search, 'elastic/app-search/client/search'
13
- autoload :QuerySuggestion, 'elastic/app-search/client/query_suggestion'
14
20
  autoload :SearchSettings, 'elastic/app-search/client/search_settings'
21
+ autoload :Synonyms, 'elastic/app-search/client/synonyms'
22
+ autoload :QuerySuggestion, 'elastic/app-search/client/query_suggestion'
15
23
 
16
24
  DEFAULT_TIMEOUT = 15
17
25
 
@@ -56,12 +64,20 @@ module Elastic
56
64
  end
57
65
  end
58
66
 
67
+ include Elastic::AppSearch::Client::Analytics
68
+ include Elastic::AppSearch::Client::Click
69
+ include Elastic::AppSearch::Client::Credentials
70
+ include Elastic::AppSearch::Client::Curations
59
71
  include Elastic::AppSearch::Client::Documents
60
72
  include Elastic::AppSearch::Client::Engines
73
+ include Elastic::AppSearch::Client::MetaEngines
74
+ include Elastic::AppSearch::Client::Logs
75
+ include Elastic::AppSearch::Client::Schema
61
76
  include Elastic::AppSearch::Client::Search
77
+ include Elastic::AppSearch::Client::SearchSettings
62
78
  include Elastic::AppSearch::Client::SignedSearchOptions
79
+ include Elastic::AppSearch::Client::Synonyms
63
80
  include Elastic::AppSearch::Client::QuerySuggestion
64
- include Elastic::AppSearch::Client::SearchSettings
65
81
  end
66
82
  end
67
83
  end
@@ -0,0 +1,25 @@
1
+ # Analytics API - https://swiftype.com/documentation/app-search/api/analytics
2
+ module Elastic
3
+ module AppSearch
4
+ class Client
5
+ module Analytics
6
+
7
+ # Returns the number of clicks received by a document in descending order.
8
+ def get_top_clicks_analytics(engine_name, options)
9
+ post("engines/#{engine_name}/analytics/clicks", options)
10
+ end
11
+
12
+ # Returns queries analytics by usage count
13
+ def get_top_queries_analytics(engine_name, options)
14
+ post("engines/#{engine_name}/analytics/queries", options)
15
+ end
16
+
17
+ # Returns the number of clicks and total number of queries over a period.
18
+ def get_count_analytics(engine_name, options)
19
+ post("engines/#{engine_name}/analytics/counts", options)
20
+ end
21
+
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,15 @@
1
+ # Click API - https://swiftype.com/documentation/app-search/api/clickthrough
2
+ module Elastic
3
+ module AppSearch
4
+ class Client
5
+ module Click
6
+
7
+ # Send data about clicked results.
8
+ def log_click_through(engine_name, options)
9
+ post("engines/#{engine_name}/documents", options)
10
+ end
11
+
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,35 @@
1
+ # Credentials API - https://swiftype.com/documentation/app-search/api/credentials
2
+ module Elastic
3
+ module AppSearch
4
+ class Client
5
+ module Credentials
6
+
7
+ # Retrieve available credentials
8
+ def list_credentials(current: 1, size: 20)
9
+ get("credentials", :page => { :current => current, :size => size })
10
+ end
11
+
12
+ # Retrieve a credential
13
+ def get_credential(name)
14
+ get("credentials/#{name}")
15
+ end
16
+
17
+ # Create a new credential
18
+ def create_credential(options)
19
+ post("credentials", options)
20
+ end
21
+
22
+ # Update an existing credential
23
+ def update_credential(name, options)
24
+ put("credentials/#{name}", options)
25
+ end
26
+
27
+ # Destroy an existing credential
28
+ def destroy_credential(name)
29
+ delete("credentials/#{name}")
30
+ end
31
+
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ # Curations API - https://swiftype.com/documentation/app-search/api/curations
2
+ module Elastic
3
+ module AppSearch
4
+ class Client
5
+ module Curations
6
+
7
+ # Retrieve available curations for the engine.
8
+ def list_curations(engine_name, current: 1, size: 20)
9
+ get("engines/#{engine_name}/curations", :page => { :current => current, :size => size })
10
+ end
11
+
12
+ # Create a new curation.
13
+ def create_curation(engine_name, options)
14
+ post("engines/#{engine_name}/curations", options)
15
+ end
16
+
17
+ # Retrieve a curation by id.
18
+ def get_curation(engine_name, id)
19
+ get("engines/#{engine_name}/curations/#{id}")
20
+ end
21
+
22
+ # Update an existing curation.
23
+ def update_curation(engine_name, id, options)
24
+ put("engines/#{engine_name}/curations/#{id}", options)
25
+ end
26
+
27
+ # Delete a curation by id.
28
+ def destroy_curation(engine_name, id)
29
+ delete("engines/#{engine_name}/curations/#{id}")
30
+ end
31
+
32
+ end
33
+ end
34
+ end
35
+ end
@@ -4,6 +4,7 @@ module Elastic
4
4
  module AppSearch
5
5
  class Client
6
6
  module Engines
7
+
7
8
  def list_engines(current: 1, size: 20)
8
9
  get("engines", :page => { :current => current, :size => size })
9
10
  end
@@ -21,6 +22,7 @@ module Elastic
21
22
  def destroy_engine(engine_name)
22
23
  delete("engines/#{engine_name}")
23
24
  end
25
+
24
26
  end
25
27
  end
26
28
  end
@@ -0,0 +1,15 @@
1
+ # Logs API - https://swiftype.com/documentation/app-search/api/logs
2
+ module Elastic
3
+ module AppSearch
4
+ class Client
5
+ module Logs
6
+
7
+ # The API Log displays API request and response data at the Engine level.
8
+ def get_api_logs(engine_name, options)
9
+ post("engines/#{engine_name}/logs/api", options)
10
+ end
11
+
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,23 @@
1
+ module Elastic
2
+ module AppSearch
3
+ class Client
4
+ module MetaEngines
5
+
6
+ ENGINE_TYPE_META = 'meta'.freeze()
7
+
8
+ def create_meta_engine(engine_name, source_engines)
9
+ post('engines', :name => engine_name, :type => ENGINE_TYPE_META, :source_engines => source_engines)
10
+ end
11
+
12
+ def add_meta_engine_sources(engine_name, source_engines)
13
+ post("engines/#{engine_name}/source_engines", source_engines)
14
+ end
15
+
16
+ def delete_meta_engine_sources(engine_name, source_engines)
17
+ delete("engines/#{engine_name}/source_engines", source_engines)
18
+ end
19
+
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,20 @@
1
+ # Schema API - https://swiftype.com/documentation/app-search/api/schema
2
+ module Elastic
3
+ module AppSearch
4
+ class Client
5
+ module Schema
6
+
7
+ # Retrieve schema for the current engine.
8
+ def get_schema(engine_name)
9
+ get("engines/#{engine_name}/schema")
10
+ end
11
+
12
+ # Create a new schema field or update existing schema for the current engine.
13
+ def update_schema(engine_name, schema)
14
+ post("engines/#{engine_name}/schema", schema)
15
+ end
16
+
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,35 @@
1
+ # Synonyms API - https://swiftype.com/documentation/app-search/api/synonyms
2
+ module Elastic
3
+ module AppSearch
4
+ class Client
5
+ module Synonyms
6
+
7
+ # Retrieve available synonym sets for the engine.
8
+ def list_synonym_sets(engine_name, current: 1, size: 20)
9
+ get("engines/#{engine_name}/synonyms", :page => { :current => current, :size => size })
10
+ end
11
+
12
+ # Retrieve a synonym set by id
13
+ def get_synonym_set(engine_name, id)
14
+ get("engines/#{engine_name}/synonyms/#{id}")
15
+ end
16
+
17
+ # Create a new synonym set
18
+ def create_synonym_set(engine_name, body)
19
+ post("engines/#{engine_name}/synonyms", body)
20
+ end
21
+
22
+ # Update an existing synonym set
23
+ def update_synonym_set(engine_name, id, body)
24
+ put("engines/#{engine_name}/synonyms/#{id}", body)
25
+ end
26
+
27
+ # Delete a synonym set by id
28
+ def destroy_synonym_set(engine_name, id)
29
+ delete("engines/#{engine_name}/synonyms/#{id}")
30
+ end
31
+
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,5 +1,5 @@
1
1
  module Elastic
2
2
  module AppSearch
3
- VERSION = '7.4.0'
3
+ VERSION = '7.8.0'
4
4
  end
5
5
  end
@@ -0,0 +1,82 @@
1
+ describe Elastic::AppSearch::Client::Analytics do
2
+ include_context 'App Search Credentials'
3
+ include_context 'Test Engine'
4
+
5
+ let(:client) { Elastic::AppSearch::Client.new(client_options) }
6
+
7
+ context '#get_top_clicks_analytics' do
8
+ subject do
9
+ client.get_top_clicks_analytics(
10
+ engine_name,
11
+ :query => 'cats',
12
+ :page => {
13
+ :size => 20,
14
+ },
15
+ :filters => {
16
+ :date => {
17
+ :from => Time.now.iso8601,
18
+ :to => Time.now.iso8601
19
+ }
20
+ }
21
+ )
22
+ end
23
+
24
+ it 'will query for analytics' do
25
+ expect(subject['results']).to(eq([]))
26
+ end
27
+ end
28
+
29
+ context '#get_top_queries_analytics' do
30
+ subject do
31
+ client.get_top_queries_analytics(
32
+ engine_name,
33
+ :page => {
34
+ :size => 20
35
+ },
36
+ :filters => {
37
+ :date => {
38
+ :from => Time.now.iso8601,
39
+ :to => Time.now.iso8601
40
+ }
41
+ }
42
+ )
43
+ end
44
+
45
+ it 'will query for analytics' do
46
+ expect(subject['results']).to(eq([]))
47
+ end
48
+ end
49
+
50
+ context '#get_count_analytics' do
51
+ let(:from) { Time.now.iso8601 }
52
+ let(:to) { Time.now.iso8601 }
53
+
54
+ subject do
55
+ client.get_count_analytics(
56
+ engine_name,
57
+ :filters => {
58
+ :all => [
59
+ {
60
+ :tag => ['mobile', 'web']
61
+ }, {
62
+ :query => 'cats'
63
+ }, {
64
+ :document_id => '163'
65
+ }, {
66
+ :date => {
67
+ :from => from,
68
+ :to => to
69
+ }
70
+ }
71
+ ]
72
+ },
73
+ :interval => 'hour'
74
+ )
75
+ end
76
+
77
+ it 'will query for analytics' do
78
+ expect(subject['results'][0]['clicks']).to(eq(0))
79
+ expect(subject['results'][0]['queries']).to(eq(0))
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,30 @@
1
+ describe Elastic::AppSearch::Client::Click do
2
+ include_context 'App Search Credentials'
3
+ include_context 'Test Engine'
4
+
5
+ let(:client) { Elastic::AppSearch::Client.new(client_options) }
6
+
7
+ context '#log_click_through' do
8
+ let(:documents) { [first_document, second_document] }
9
+ let(:first_document_id) { 'id' }
10
+ let(:first_document) { { 'id' => first_document_id } }
11
+ let(:second_document_id) { 'another_id' }
12
+ let(:second_document) { { 'id' => second_document_id } }
13
+
14
+ before { client.index_documents(engine_name, documents) }
15
+
16
+ subject do
17
+ client.log_click_through(
18
+ engine_name,
19
+ :query => 'cat videos',
20
+ :document_id => first_document_id,
21
+ :request_id => 'e4c4dea0bd7ad3d2f676575ef16dc7d2',
22
+ :tags => ['firefox', 'web browser']
23
+ )
24
+ end
25
+
26
+ it 'will log a click' do
27
+ expect(subject[0]['id']).not_to(be_empty)
28
+ end
29
+ end
30
+ end
@@ -2,42 +2,9 @@ require 'config_helper'
2
2
  require 'securerandom'
3
3
 
4
4
  describe Elastic::AppSearch::Client do
5
- let(:engine_name) { "ruby-client-test-#{SecureRandom.hex}" }
6
-
7
5
  include_context 'App Search Credentials'
8
6
  let(:client) { Elastic::AppSearch::Client.new(client_options) }
9
7
 
10
- before(:all) do
11
- # Bootstraps a static engine for 'read-only' options that require indexing
12
- # across the test suite
13
- @static_engine_name = "ruby-client-test-static-#{SecureRandom.hex}"
14
- as_api_key = ConfigHelper.get_as_api_key
15
- as_host_identifier = ConfigHelper.get_as_host_identifier
16
- as_api_endpoint = ConfigHelper.get_as_api_endpoint
17
- client_options = ConfigHelper.get_client_options(as_api_key, as_host_identifier, as_api_endpoint)
18
- @static_client = Elastic::AppSearch::Client.new(client_options)
19
- @static_client.create_engine(@static_engine_name)
20
-
21
- @document1 = { 'id' => '1', 'title' => 'The Great Gatsby' }
22
- @document2 = { 'id' => '2', 'title' => 'Catcher in the Rye' }
23
- @documents = [@document1, @document2]
24
- @static_client.index_documents(@static_engine_name, @documents)
25
-
26
- # Wait until documents are indexed
27
- start = Time.now
28
- ready = false
29
- until (ready)
30
- sleep(3)
31
- results = @static_client.search(@static_engine_name, '')
32
- ready = true if results['results'].length == 2
33
- ready = true if (Time.now - start).to_i >= 120 # Time out after 2 minutes
34
- end
35
- end
36
-
37
- after(:all) do
38
- @static_client.destroy_engine(@static_engine_name)
39
- end
40
-
41
8
  describe '#create_signed_search_key' do
42
9
  let(:key) { 'private-xxxxxxxxxxxxxxxxxxxx' }
43
10
  let(:api_key_name) { 'private-key' }
@@ -52,435 +19,40 @@ describe Elastic::AppSearch::Client do
52
19
  end
53
20
 
54
21
  it 'should build a valid jwt' do
55
- decoded_token = JWT.decode subject, key, true, { algorithm: 'HS256' }
56
- expect(decoded_token[0]['api_key_name']).to eq(api_key_name)
57
- expect(decoded_token[0]['query']).to eq('cat')
22
+ decoded_token = JWT.decode(subject, key, true, :algorithm => 'HS256')
23
+ expect(decoded_token[0]['api_key_name']).to(eq(api_key_name))
24
+ expect(decoded_token[0]['query']).to(eq('cat'))
58
25
  end
59
26
  end
60
27
 
61
28
  describe 'Requests' do
62
29
  it 'should include client name and version in headers' do
63
- stub_request(:any, "#{client_options[:host_identifier]}.api.swiftype.com/api/as/v1/engines")
64
- client.list_engines
65
- expect(WebMock).to have_requested(:get, "https://#{client_options[:host_identifier]}.api.swiftype.com/api/as/v1/engines")
66
- .with(
67
- :headers => {
68
- 'X-Swiftype-Client' => 'elastic-app-search-ruby',
69
- 'X-Swiftype-Client-Version' => Elastic::AppSearch::VERSION
70
- }
71
- )
72
- end
73
- end
74
-
75
- context 'Documents' do
76
- let(:document) { { 'url' => 'http://www.youtube.com/watch?v=v1uyQZNg2vE' } }
77
-
78
- before do
79
- client.create_engine(engine_name) rescue Elastic::AppSearch::BadRequest
80
- end
81
-
82
- after do
83
- client.destroy_engine(engine_name) rescue Elastic::AppSearch::NonExistentRecord
84
- end
85
-
86
- describe '#index_document' do
87
- subject { client.index_document(engine_name, document) }
88
-
89
- it 'should return a processed document status hash' do
90
- expect(subject).to match('id' => anything)
91
- end
92
-
93
- context 'when the document has an id' do
94
- let(:id) { 'some_id' }
95
- let(:document) { { 'id' => id, 'url' => 'http://www.youtube.com/watch?v=v1uyQZNg2vE' } }
96
-
97
- it 'should return a processed document status hash with the same id' do
98
- expect(subject).to eq('id' => id)
99
- end
100
- end
101
-
102
- context 'when a document has processing errors' do
103
- let(:document) { { 'id' => 'too long' * 100 } }
104
-
105
- it 'should raise an error when the API returns errors in the response' do
106
- expect do
107
- subject
108
- end.to raise_error(Elastic::AppSearch::InvalidDocument, /Invalid field/)
109
- end
110
- end
111
-
112
- context 'when a document has a Ruby Time object' do
113
- let(:time_rfc3339) { '2018-01-01T01:01:01+00:00' }
114
- let(:time_object) { Time.parse(time_rfc3339) }
115
- let(:document) { { 'created_at' => time_object } }
116
-
117
- it 'should serialize the time object in RFC 3339' do
118
- response = subject
119
- expect(response).to have_key('id')
120
- document_id = response.fetch('id')
121
- expect do
122
- documents = client.get_documents(engine_name, [document_id])
123
- expect(documents.size).to eq(1)
124
- expect(documents.first['created_at']).to eq(time_rfc3339)
125
- end.to_not raise_error
126
- end
127
- end
128
- end
129
-
130
- describe '#index_documents' do
131
- let(:documents) { [document, second_document] }
132
- let(:second_document_id) { 'another_id' }
133
- let(:second_document) { { 'id' => second_document_id, 'url' => 'https://www.youtube.com/watch?v=9T1vfsHYiKY' } }
134
- subject { client.index_documents(engine_name, documents) }
135
-
136
- it 'should return an array of document status hashes' do
137
- expect(subject).to match(
138
- [
139
- { 'id' => anything, 'errors' => [] },
140
- { 'id' => second_document_id, 'errors' => [] }
141
- ]
142
- )
143
- end
144
-
145
- context 'when one of the documents has processing errors' do
146
- let(:second_document) { { 'id' => 'too long' * 100 } }
147
-
148
- it 'should return respective errors in an array of document processing hashes' do
149
- expect(subject).to match(
150
- [
151
- { 'id' => anything, 'errors' => [] },
152
- { 'id' => anything, 'errors' => ['Invalid field type: id must be less than 800 characters'] },
153
- ]
30
+ if (client_options[:api_endpoint])
31
+ stub_request(:any, "#{client_options[:api_endpoint]}engines")
32
+ client.list_engines
33
+ expect(WebMock).to(
34
+ have_requested(:get, "#{client_options[:api_endpoint]}engines")
35
+ .with(
36
+ :headers => {
37
+ 'X-Swiftype-Client' => 'elastic-app-search-ruby',
38
+ 'X-Swiftype-Client-Version' => Elastic::AppSearch::VERSION
39
+ }
154
40
  )
155
- end
156
- end
157
- end
158
-
159
- describe '#update_documents' do
160
- let(:documents) { [document, second_document] }
161
- let(:second_document_id) { 'another_id' }
162
- let(:second_document) { { 'id' => second_document_id, 'url' => 'https://www.youtube.com/watch?v=9T1vfsHYiKY' } }
163
- let(:updates) do
164
- [
165
- {
166
- 'id' => second_document_id,
167
- 'url' => 'https://www.example.com'
168
- }
169
- ]
170
- end
171
-
172
- subject { client.update_documents(engine_name, updates) }
173
-
174
- before do
175
- client.index_documents(engine_name, documents)
176
- end
177
-
178
- # Note that since indexing a document takes up to a minute,
179
- # we don't expect this to succeed, so we simply verify that
180
- # the request responded with the correct 'id', even though
181
- # the 'errors' object likely contains errors.
182
- it 'should update existing documents' do
183
- expect(subject).to match(['id' => second_document_id, 'errors' => anything])
184
- end
185
- end
186
-
187
- describe '#get_documents' do
188
- let(:documents) { [first_document, second_document] }
189
- let(:first_document_id) { 'id' }
190
- let(:first_document) { { 'id' => first_document_id, 'url' => 'https://www.youtube.com/watch?v=v1uyQZNg2vE' } }
191
- let(:second_document_id) { 'another_id' }
192
- let(:second_document) { { 'id' => second_document_id, 'url' => 'https://www.youtube.com/watch?v=9T1vfsHYiKY' } }
193
-
194
- subject { client.get_documents(engine_name, [first_document_id, second_document_id]) }
195
-
196
- before do
197
- client.index_documents(engine_name, documents)
198
- end
199
-
200
- it 'will return documents by id' do
201
- response = subject
202
- expect(response.size).to eq(2)
203
- expect(response[0]['id']).to eq(first_document_id)
204
- expect(response[1]['id']).to eq(second_document_id)
205
- end
206
- end
207
-
208
- describe '#list_documents' do
209
- let(:documents) { [first_document, second_document] }
210
- let(:first_document_id) { 'id' }
211
- let(:first_document) { { 'id' => first_document_id, 'url' => 'https://www.youtube.com/watch?v=v1uyQZNg2vE' } }
212
- let(:second_document_id) { 'another_id' }
213
- let(:second_document) { { 'id' => second_document_id, 'url' => 'https://www.youtube.com/watch?v=9T1vfsHYiKY' } }
214
-
215
- before do
216
- client.index_documents(engine_name, documents)
217
- end
218
-
219
- context 'when no options are specified' do
220
- it 'will return all documents' do
221
- response = client.list_documents(engine_name)
222
- expect(response['results'].size).to eq(2)
223
- expect(response['results'][0]['id']).to eq(first_document_id)
224
- expect(response['results'][1]['id']).to eq(second_document_id)
225
- end
226
- end
227
-
228
- context 'when options are specified' do
229
- it 'will return all documents' do
230
- response = client.list_documents(engine_name, :page => { :size => 1, :current => 2 })
231
- expect(response['results'].size).to eq(1)
232
- expect(response['results'][0]['id']).to eq(second_document_id)
233
- end
234
- end
235
- end
236
- end
237
-
238
- context 'Search' do
239
- describe '#search' do
240
- subject { @static_client.search(@static_engine_name, query, options) }
241
- let(:query) { '' }
242
- let(:options) { { 'page' => { 'size' => 2 } } }
243
-
244
- it 'should execute a search query' do
245
- expect(subject).to match(
246
- 'meta' => anything,
247
- 'results' => [anything, anything]
248
41
  )
249
- end
250
- end
251
-
252
- describe '#multi_search' do
253
- subject { @static_client.multi_search(@static_engine_name, queries) }
254
-
255
- context 'when options are provided' do
256
- let(:queries) do
257
- [
258
- { 'query' => 'gatsby', 'options' => { 'page' => { 'size' => 1 } } },
259
- { 'query' => 'catcher', 'options' => { 'page' => { 'size' => 1 } } }
260
- ]
261
- end
262
-
263
- it 'should execute a multi search query' do
264
- response = subject
265
- expect(response).to match(
266
- [
267
- {
268
- 'meta' => anything,
269
- 'results' => [{ 'id' => { 'raw' => '1' }, 'title' => anything, '_meta' => anything }]
270
- },
271
- {
272
- 'meta' => anything,
273
- 'results' => [{ 'id' => { 'raw' => '2' }, 'title' => anything, '_meta' => anything }]
274
- }
275
- ]
276
- )
277
- end
278
- end
279
-
280
- context 'when options are omitted' do
281
- let(:queries) do
282
- [
283
- { 'query' => 'gatsby' },
284
- { 'query' => 'catcher' }
285
- ]
286
- end
287
-
288
- it 'should execute a multi search query' do
289
- response = subject
290
- expect(response).to match(
291
- [
292
- {
293
- 'meta' => anything,
294
- 'results' => [{ 'id' => { 'raw' => '1' }, 'title' => anything, '_meta' => anything }]
295
- },
296
- {
297
- 'meta' => anything,
298
- 'results' => [{ 'id' => { 'raw' => '2' }, 'title' => anything, '_meta' => anything }]
299
- }
300
- ]
301
- )
302
- end
303
- end
304
-
305
- context 'when a search is bad' do
306
- let(:queries) do
307
- [
308
- {
309
- 'query' => 'cat',
310
- 'options' => { 'search_fields' => { 'taco' => {} } }
311
- }, {
312
- 'query' => 'dog',
313
- 'options' => { 'search_fields' => { 'body' => {} } }
42
+ else
43
+ # CI runs against saas, so we keep this around for now. CI should be updated
44
+ # to use slef-managed and we should drop support "host_identifier" this.
45
+ stub_request(:any, "#{client_options[:host_identifier]}.api.swiftype.com/api/as/v1/engines")
46
+ client.list_engines
47
+ expect(WebMock).to(
48
+ have_requested(:get, "https://#{client_options[:host_identifier]}.api.swiftype.com/api/as/v1/engines")
49
+ .with(
50
+ :headers => {
51
+ 'X-Swiftype-Client' => 'elastic-app-search-ruby',
52
+ 'X-Swiftype-Client-Version' => Elastic::AppSearch::VERSION
314
53
  }
315
- ]
316
- end
317
-
318
- it 'should throw an appropriate error' do
319
- expect { subject }.to raise_error do |e|
320
- expect(e).to be_a(Elastic::AppSearch::BadRequest)
321
- expect(e.errors).to eq(['Search fields contains invalid field: taco', 'Search fields contains invalid field: body'])
322
- end
323
- end
324
- end
325
- end
326
- end
327
-
328
- context 'QuerySuggest' do
329
- describe '#query_suggestion' do
330
- let(:query) { 'cat' }
331
- let(:options) { { :size => 3, :types => { :documents => { :fields => ['title'] } } } }
332
-
333
- context 'when options are provided' do
334
- subject { @static_client.query_suggestion(@static_engine_name, query, options) }
335
-
336
- it 'should request query suggestions' do
337
- expect(subject).to match(
338
- 'meta' => anything,
339
- 'results' => anything
340
- )
341
- end
342
- end
343
-
344
- context 'when options are omitted' do
345
- subject { @static_client.query_suggestion(@static_engine_name, query) }
346
-
347
- it 'should request query suggestions' do
348
- expect(subject).to match(
349
- 'meta' => anything,
350
- 'results' => anything
351
54
  )
352
- end
353
- end
354
- end
355
- end
356
-
357
- context 'SearchSettings' do
358
- let(:default_settings) { {
359
- "search_fields" => {
360
- "id" => {
361
- "weight" => 1
362
- }
363
- },
364
- "result_fields" => {"id"=>{"raw"=>{}}},
365
- "boosts" => {}
366
- } }
367
-
368
- let(:updated_settings) { {
369
- "search_fields" => {
370
- "id" => {
371
- "weight" => 3
372
- }
373
- },
374
- "result_fields" => {"id"=>{"raw"=>{}}},
375
- "boosts" => {}
376
- } }
377
-
378
- before(:each) do
379
- client.create_engine(engine_name) rescue Elastic::AppSearch::BadRequest
380
- end
381
-
382
- after(:each) do
383
- client.destroy_engine(engine_name) rescue Elastic::AppSearch::NonExistentRecord
384
- end
385
-
386
- describe '#show_settings' do
387
- subject { client.show_settings(engine_name) }
388
-
389
- it 'should return default settings' do
390
- expect(subject).to match(default_settings)
391
- end
392
- end
393
-
394
- describe '#update_settings' do
395
- subject { client.show_settings(engine_name) }
396
-
397
- before do
398
- client.update_settings(engine_name, updated_settings)
399
- end
400
-
401
- it 'should update search settings' do
402
- expect(subject).to match(updated_settings)
403
- end
404
- end
405
-
406
- describe '#reset_settings' do
407
- subject { client.show_settings(engine_name) }
408
-
409
- before do
410
- client.update_settings(engine_name, updated_settings)
411
- client.reset_settings(engine_name)
412
- end
413
-
414
- it 'should reset search settings' do
415
- expect(subject).to match(default_settings)
416
- end
417
- end
418
- end
419
-
420
- context 'Engines' do
421
- after do
422
- client.destroy_engine(engine_name) rescue Elastic::AppSearch::NonExistentRecord
423
- end
424
-
425
- context '#create_engine' do
426
- it 'should create an engine when given a right set of parameters' do
427
- expect { client.get_engine(engine_name) }.to raise_error(Elastic::AppSearch::NonExistentRecord)
428
- client.create_engine(engine_name)
429
- expect { client.get_engine(engine_name) }.to_not raise_error
430
- end
431
-
432
- it 'should accept an optional language parameter' do
433
- expect { client.get_engine(engine_name) }.to raise_error(Elastic::AppSearch::NonExistentRecord)
434
- client.create_engine(engine_name, 'da')
435
- expect(client.get_engine(engine_name)).to match('name' => anything, 'type' => anything, 'language' => 'da')
436
- end
437
-
438
- it 'should return an engine object' do
439
- engine = client.create_engine(engine_name)
440
- expect(engine).to be_kind_of(Hash)
441
- expect(engine['name']).to eq(engine_name)
442
- end
443
-
444
- it 'should return an error when the engine name has already been taken' do
445
- client.create_engine(engine_name)
446
- expect { client.create_engine(engine_name) }.to raise_error do |e|
447
- expect(e).to be_a(Elastic::AppSearch::BadRequest)
448
- expect(e.errors).to eq(['Name is already taken'])
449
- end
450
- end
451
- end
452
-
453
- context '#list_engines' do
454
- it 'should return an array with a list of engines' do
455
- expect(client.list_engines['results']).to be_an(Array)
456
- end
457
-
458
- it 'should include the engine name in listed objects' do
459
- client.create_engine(engine_name)
460
-
461
- engines = client.list_engines['results']
462
- expect(engines.find { |e| e['name'] == engine_name }).to_not be_nil
463
- end
464
-
465
- it 'should include the engine name in listed objects with pagination' do
466
- client.create_engine(engine_name)
467
-
468
- engines = client.list_engines(:current => 1, :size => 20)['results']
469
- expect(engines.find { |e| e['name'] == engine_name }).to_not be_nil
470
- end
471
- end
472
-
473
- context '#destroy_engine' do
474
- it 'should destroy the engine if it exists' do
475
- client.create_engine(engine_name)
476
- expect { client.get_engine(engine_name) }.to_not raise_error
477
-
478
- client.destroy_engine(engine_name)
479
- expect { client.get_engine(engine_name) }.to raise_error(Elastic::AppSearch::NonExistentRecord)
480
- end
481
-
482
- it 'should raise an error if the engine does not exist' do
483
- expect { client.destroy_engine(engine_name) }.to raise_error(Elastic::AppSearch::NonExistentRecord)
55
+ )
484
56
  end
485
57
  end
486
58
  end
@@ -489,12 +61,12 @@ describe Elastic::AppSearch::Client do
489
61
  context 'host_identifier' do
490
62
  it 'sets the base url correctly' do
491
63
  client = Elastic::AppSearch::Client.new(:host_identifier => 'host-asdf', :api_key => 'foo')
492
- expect(client.api_endpoint).to eq('https://host-asdf.api.swiftype.com/api/as/v1/')
64
+ expect(client.api_endpoint).to(eq('https://host-asdf.api.swiftype.com/api/as/v1/'))
493
65
  end
494
66
 
495
67
  it 'sets the base url correctly using deprecated as_host_key' do
496
68
  client = Elastic::AppSearch::Client.new(:account_host_key => 'host-asdf', :api_key => 'foo')
497
- expect(client.api_endpoint).to eq('https://host-asdf.api.swiftype.com/api/as/v1/')
69
+ expect(client.api_endpoint).to(eq('https://host-asdf.api.swiftype.com/api/as/v1/'))
498
70
  end
499
71
  end
500
72
  end