elastic-app-search 7.4.0 → 7.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,6 +3,10 @@ module ConfigHelper
3
3
  ENV.fetch('AS_API_KEY', 'API_KEY')
4
4
  end
5
5
 
6
+ def ConfigHelper.get_as_admin_key
7
+ ENV.fetch('AS_ADMIN_KEY', 'ADMIN_KEY')
8
+ end
9
+
6
10
  def ConfigHelper.get_as_host_identifier
7
11
  ENV['AS_ACCOUNT_HOST_KEY'] || ENV['AS_HOST_IDENTIFIER'] || 'ACCOUNT_HOST_KEY'
8
12
  end
@@ -0,0 +1,75 @@
1
+ require 'securerandom'
2
+
3
+ describe Elastic::AppSearch::Client::Credentials do
4
+ include_context 'App Search Admin Credentials'
5
+ include_context 'Test Engine'
6
+
7
+ let(:client) { Elastic::AppSearch::Client.new(client_options) }
8
+ let(:key_name) { "spec-key-#{SecureRandom.hex}" }
9
+ let(:api_key) do
10
+ {
11
+ :name => key_name,
12
+ :type => 'private',
13
+ :read => true,
14
+ :write => false,
15
+ :access_all_engines => false,
16
+ :engines => [
17
+ engine_name
18
+ ]
19
+ }
20
+ end
21
+
22
+ context '#create_credential' do
23
+ after { client.destroy_credential(key_name) }
24
+ subject { client.create_credential(api_key) }
25
+
26
+ it 'will create an API Key' do
27
+ expect(subject['name']).to(eq(key_name))
28
+ end
29
+ end
30
+
31
+ context '#get_credential' do
32
+ after { client.destroy_credential(key_name) }
33
+ before { client.create_credential(api_key) }
34
+ subject { client.get_credential(key_name) }
35
+
36
+ it 'will retrieve an API Key' do
37
+ expect(subject['name']).to(eq(key_name))
38
+ end
39
+ end
40
+
41
+ context '#update_credential' do
42
+ let(:updated_api_key) do
43
+ api_key['write'] = true
44
+ api_key
45
+ end
46
+
47
+ before { client.create_credential(api_key) }
48
+ after { client.destroy_credential(key_name) }
49
+ subject { client.update_credential(key_name, updated_api_key) }
50
+
51
+ it 'will update an API Key' do
52
+ expect(subject['name']).to(eq(key_name))
53
+ expect(subject['write']).to(eq(true))
54
+ end
55
+ end
56
+
57
+ context '#list_credentials' do
58
+ before { client.create_credential(api_key) }
59
+ after { client.destroy_credential(key_name) }
60
+ subject { client.list_credentials }
61
+
62
+ it 'will list all API Keys' do
63
+ expect(subject['results'].map { |r| r['name'] }.include?(key_name)).to(eq(true))
64
+ end
65
+ end
66
+
67
+ context '#destroy_credential' do
68
+ before { client.create_credential(api_key) }
69
+ subject { client.destroy_credential(key_name) }
70
+
71
+ it 'will delete an API Key' do
72
+ expect(subject['deleted']).to(eq(true))
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,82 @@
1
+ describe Elastic::AppSearch::Client::Curations do
2
+ include_context 'App Search Credentials'
3
+ include_context 'Static Test Engine'
4
+
5
+ let(:client) { Elastic::AppSearch::Client.new(client_options) }
6
+
7
+ let(:curation) do
8
+ {
9
+ 'queries' => [
10
+ 'zion'
11
+ ],
12
+ 'promoted' => [
13
+ document1['id']
14
+ ],
15
+ 'hidden' => [
16
+ document2['id']
17
+ ]
18
+ }
19
+ end
20
+ let(:curation_id) { client.create_curation(engine_name, curation)['id'] }
21
+
22
+ after(:each) do
23
+ begin
24
+ client.destroy_curation(engine_name, curation_id)
25
+ rescue
26
+ # Ignore it
27
+ end
28
+ end
29
+
30
+ context '#create_curation' do
31
+ it 'will create a curation' do
32
+ expect(curation_id).not_to(be_empty)
33
+ end
34
+ end
35
+
36
+ context '#get_curation' do
37
+ subject { client.get_curation(engine_name, curation_id) }
38
+
39
+ it 'will retrieve a curation' do
40
+ expect(subject['queries']).to(eq(['zion']))
41
+ end
42
+ end
43
+
44
+ context '#update_curation' do
45
+ let(:updated_curation) do
46
+ {
47
+ 'queries' => [
48
+ 'zion', 'lion'
49
+ ],
50
+ 'promoted' => [
51
+ document1['id']
52
+ ]
53
+ }
54
+ end
55
+ subject { client.update_curation(engine_name, curation_id, updated_curation) }
56
+
57
+ it 'will update a curation' do
58
+ expect(subject['id']).to(eq(curation_id))
59
+ end
60
+ end
61
+
62
+ context '#list_curations' do
63
+ subject { client.list_curations(engine_name, :current => 1, :size => 5) }
64
+
65
+ it 'will list curations' do
66
+ expect(subject['results']).to(eq([]))
67
+ end
68
+
69
+ it 'supports paging params' do
70
+ expect(subject['meta']['page']['current']).to(eq(1))
71
+ expect(subject['meta']['page']['size']).to(eq(5))
72
+ end
73
+ end
74
+
75
+ context '#destroy_curation' do
76
+ subject { client.destroy_curation(engine_name, curation_id) }
77
+
78
+ it 'will destroy a curation' do
79
+ expect(subject['deleted']).to(eq(true))
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,159 @@
1
+ describe Elastic::AppSearch::Client::Documents 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 'Documents' do
8
+ let(:document) { { 'url' => 'http://www.youtube.com/watch?v=v1uyQZNg2vE' } }
9
+
10
+ describe '#index_document' do
11
+ subject { client.index_document(engine_name, document) }
12
+
13
+ it 'should return a processed document status hash' do
14
+ expect(subject).to(match('id' => anything))
15
+ end
16
+
17
+ context 'when the document has an id' do
18
+ let(:id) { 'some_id' }
19
+ let(:document) { { 'id' => id, 'url' => 'http://www.youtube.com/watch?v=v1uyQZNg2vE' } }
20
+
21
+ it 'should return a processed document status hash with the same id' do
22
+ expect(subject).to(eq('id' => id))
23
+ end
24
+ end
25
+
26
+ context 'when a document has processing errors' do
27
+ let(:document) { { 'id' => 'too long' * 100 } }
28
+
29
+ it 'should raise an error when the API returns errors in the response' do
30
+ expect do
31
+ subject
32
+ end.to(raise_error(Elastic::AppSearch::InvalidDocument, /Invalid field/))
33
+ end
34
+ end
35
+
36
+ context 'when a document has a Ruby Time object' do
37
+ let(:time_rfc3339) { '2018-01-01T01:01:01+00:00' }
38
+ let(:time_object) { Time.parse(time_rfc3339) }
39
+ let(:document) { { 'created_at' => time_object } }
40
+
41
+ it 'should serialize the time object in RFC 3339' do
42
+ response = subject
43
+ expect(response).to(have_key('id'))
44
+ document_id = response.fetch('id')
45
+ expect do
46
+ documents = client.get_documents(engine_name, [document_id])
47
+ expect(documents.size).to(eq(1))
48
+ expect(documents.first['created_at']).to(eq(time_rfc3339))
49
+ end.to_not(raise_error)
50
+ end
51
+ end
52
+ end
53
+
54
+ describe '#index_documents' do
55
+ let(:documents) { [document, second_document] }
56
+ let(:second_document_id) { 'another_id' }
57
+ let(:second_document) { { 'id' => second_document_id, 'url' => 'https://www.youtube.com/watch?v=9T1vfsHYiKY' } }
58
+ subject { client.index_documents(engine_name, documents) }
59
+
60
+ it 'should return an array of document status hashes' do
61
+ expected = [
62
+ { 'id' => anything, 'errors' => [] },
63
+ { 'id' => second_document_id, 'errors' => [] }
64
+ ]
65
+ expect(subject).to(match(expected))
66
+ end
67
+
68
+ context 'when one of the documents has processing errors' do
69
+ let(:second_document) { { 'id' => 'too long' * 100 } }
70
+
71
+ it 'should return respective errors in an array of document processing hashes' do
72
+ expected = [
73
+ { 'id' => anything, 'errors' => [] },
74
+ { 'id' => anything, 'errors' => ['Invalid field type: id must be less than 800 characters'] },
75
+ ]
76
+ expect(subject).to(match(expected))
77
+ end
78
+ end
79
+ end
80
+
81
+ describe '#update_documents' do
82
+ let(:documents) { [document, second_document] }
83
+ let(:second_document_id) { 'another_id' }
84
+ let(:second_document) { { 'id' => second_document_id, 'url' => 'https://www.youtube.com/watch?v=9T1vfsHYiKY' } }
85
+ let(:updates) do
86
+ [
87
+ {
88
+ 'id' => second_document_id,
89
+ 'url' => 'https://www.example.com'
90
+ }
91
+ ]
92
+ end
93
+
94
+ subject { client.update_documents(engine_name, updates) }
95
+
96
+ before do
97
+ client.index_documents(engine_name, documents)
98
+ end
99
+
100
+ # Note that since indexing a document takes up to a minute,
101
+ # we don't expect this to succeed, so we simply verify that
102
+ # the request responded with the correct 'id', even though
103
+ # the 'errors' object likely contains errors.
104
+ it 'should update existing documents' do
105
+ expect(subject).to(match(['id' => second_document_id, 'errors' => anything]))
106
+ end
107
+ end
108
+
109
+ describe '#get_documents' do
110
+ let(:documents) { [first_document, second_document] }
111
+ let(:first_document_id) { 'id' }
112
+ let(:first_document) { { 'id' => first_document_id, 'url' => 'https://www.youtube.com/watch?v=v1uyQZNg2vE' } }
113
+ let(:second_document_id) { 'another_id' }
114
+ let(:second_document) { { 'id' => second_document_id, 'url' => 'https://www.youtube.com/watch?v=9T1vfsHYiKY' } }
115
+
116
+ subject { client.get_documents(engine_name, [first_document_id, second_document_id]) }
117
+
118
+ before do
119
+ client.index_documents(engine_name, documents)
120
+ end
121
+
122
+ it 'will return documents by id' do
123
+ response = subject
124
+ expect(response.size).to(eq(2))
125
+ expect(response[0]['id']).to(eq(first_document_id))
126
+ expect(response[1]['id']).to(eq(second_document_id))
127
+ end
128
+ end
129
+
130
+ describe '#list_documents' do
131
+ let(:documents) { [first_document, second_document] }
132
+ let(:first_document_id) { 'id' }
133
+ let(:first_document) { { 'id' => first_document_id, 'url' => 'https://www.youtube.com/watch?v=v1uyQZNg2vE' } }
134
+ let(:second_document_id) { 'another_id' }
135
+ let(:second_document) { { 'id' => second_document_id, 'url' => 'https://www.youtube.com/watch?v=9T1vfsHYiKY' } }
136
+
137
+ before do
138
+ client.index_documents(engine_name, documents)
139
+ end
140
+
141
+ context 'when no options are specified' do
142
+ it 'will return all documents' do
143
+ response = client.list_documents(engine_name)
144
+ expect(response['results'].size).to(eq(2))
145
+ expect(response['results'][0]['id']).to(eq(first_document_id))
146
+ expect(response['results'][1]['id']).to(eq(second_document_id))
147
+ end
148
+ end
149
+
150
+ context 'when options are specified' do
151
+ it 'will return all documents' do
152
+ response = client.list_documents(engine_name, :page => { :size => 1, :current => 2 })
153
+ expect(response['results'].size).to(eq(1))
154
+ expect(response['results'][0]['id']).to(eq(second_document_id))
155
+ end
156
+ end
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,74 @@
1
+ describe Elastic::AppSearch::Client::Engines do
2
+ include_context 'App Search Credentials'
3
+ include_context 'Engine Name'
4
+
5
+ let(:client) { Elastic::AppSearch::Client.new(client_options) }
6
+
7
+ context 'Engines' do
8
+ after do
9
+ client.destroy_engine(engine_name) rescue Elastic::AppSearch::NonExistentRecord
10
+ end
11
+
12
+ context '#create_engine' do
13
+ it 'should create an engine when given a right set of parameters' do
14
+ expect { client.get_engine(engine_name) }.to(raise_error(Elastic::AppSearch::NonExistentRecord))
15
+ client.create_engine(engine_name)
16
+ expect { client.get_engine(engine_name) }.to_not(raise_error)
17
+ end
18
+
19
+ it 'should accept an optional language parameter' do
20
+ expect { client.get_engine(engine_name) }.to(raise_error(Elastic::AppSearch::NonExistentRecord))
21
+ client.create_engine(engine_name, 'da')
22
+ expect(client.get_engine(engine_name)).to(match('name' => anything, 'type' => anything, 'language' => 'da'))
23
+ end
24
+
25
+ it 'should return an engine object' do
26
+ engine = client.create_engine(engine_name)
27
+ expect(engine).to(be_kind_of(Hash))
28
+ expect(engine['name']).to(eq(engine_name))
29
+ end
30
+
31
+ it 'should return an error when the engine name has already been taken' do
32
+ client.create_engine(engine_name)
33
+ expect { client.create_engine(engine_name) }.to(raise_error) do |e|
34
+ expect(e).to(be_a(Elastic::AppSearch::BadRequest))
35
+ expect(e.errors).to(eq(['Name is already taken']))
36
+ end
37
+ end
38
+ end
39
+
40
+ context '#list_engines' do
41
+ it 'should return an array with a list of engines' do
42
+ expect(client.list_engines['results']).to(be_an(Array))
43
+ end
44
+
45
+ it 'should include the engine name in listed objects' do
46
+ client.create_engine(engine_name)
47
+
48
+ engines = client.list_engines['results']
49
+ expect(engines.find { |e| e['name'] == engine_name }).to_not(be_nil)
50
+ end
51
+
52
+ it 'should include the engine name in listed objects with pagination' do
53
+ client.create_engine(engine_name)
54
+
55
+ engines = client.list_engines(:current => 1, :size => 20)['results']
56
+ expect(engines.find { |e| e['name'] == engine_name }).to_not(be_nil)
57
+ end
58
+ end
59
+
60
+ context '#destroy_engine' do
61
+ it 'should destroy the engine if it exists' do
62
+ client.create_engine(engine_name)
63
+ expect { client.get_engine(engine_name) }.to_not(raise_error)
64
+
65
+ client.destroy_engine(engine_name)
66
+ expect { client.get_engine(engine_name) }.to(raise_error(Elastic::AppSearch::NonExistentRecord))
67
+ end
68
+
69
+ it 'should raise an error if the engine does not exist' do
70
+ expect { client.destroy_engine(engine_name) }.to(raise_error(Elastic::AppSearch::NonExistentRecord))
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,33 @@
1
+ describe Elastic::AppSearch::Client::Logs 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_api_logs' do
8
+ let(:from) { Time.now.iso8601 }
9
+ let(:to) { Time.now.iso8601 }
10
+
11
+ subject do
12
+ options = {
13
+ :filters => {
14
+ :date => {
15
+ :from => from,
16
+ :to => to
17
+ }
18
+ },
19
+ :page => {
20
+ :total_results => 100,
21
+ :size => 20
22
+ },
23
+ :query => 'search',
24
+ :sort_direction => 'desc'
25
+ }
26
+ client.get_api_logs(engine_name, options)
27
+ end
28
+
29
+ it 'will retrieve api logs' do
30
+ expect(subject['results']).to(eq([]))
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,37 @@
1
+ describe Elastic::AppSearch::Client::Search do
2
+ include_context 'App Search Credentials'
3
+ include_context 'Static Test Engine'
4
+
5
+ let(:client) { Elastic::AppSearch::Client.new(client_options) }
6
+
7
+ context 'QuerySuggest' do
8
+ describe '#query_suggestion' do
9
+ let(:query) { 'cat' }
10
+ let(:options) { { :size => 3, :types => { :documents => { :fields => ['title'] } } } }
11
+
12
+ context 'when options are provided' do
13
+ subject { client.query_suggestion(engine_name, query, options) }
14
+
15
+ it 'should request query suggestions' do
16
+ expected = {
17
+ 'meta' => anything,
18
+ 'results' => anything
19
+ }
20
+ expect(subject).to(match(expected))
21
+ end
22
+ end
23
+
24
+ context 'when options are omitted' do
25
+ subject { client.query_suggestion(engine_name, query) }
26
+
27
+ it 'should request query suggestions' do
28
+ expected = {
29
+ 'meta' => anything,
30
+ 'results' => anything
31
+ }
32
+ expect(subject).to(match(expected))
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end