search_flip 2.0.0.beta2 → 2.0.0.beta3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,265 @@
1
+
2
+ require File.expand_path("../spec_helper", __dir__)
3
+
4
+ RSpec.describe SearchFlip::Aggregation do
5
+ describe "#where" do
6
+ it "sets up the constraints correctly for the aggregation and is chainable" do
7
+ product1 = create(:product, category: "category1", title: "title", description: "description")
8
+ product2 = create(:product, category: "category2", title: "title", description: "description")
9
+ product3 = create(:product, category: "category1", title: "title", description: "description")
10
+ product4 = create(:product, category: "category2", title: "title", description: "other")
11
+ product5 = create(:product, category: "category1", title: "other", description: "description")
12
+
13
+ ProductIndex.import [product1, product2, product3, product4, product5]
14
+
15
+ query = ProductIndex.aggregate(category: {}) do |aggregation|
16
+ aggregation.where(title: "title").where(description: "description").aggregate(:category)
17
+ end
18
+
19
+ aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[:key]] = bucket.doc_count }
20
+
21
+ expect(aggregations).to eq("category1" => 2, "category2" => 1)
22
+ end
23
+
24
+ it "works with arrays" do
25
+ product1 = create(:product, category: "category1", title: "title1", description: "description1")
26
+ product2 = create(:product, category: "category2", title: "title2", description: "description2")
27
+ product3 = create(:product, category: "category1", title: "title3", description: "description3")
28
+ product4 = create(:product, category: "category2", title: "title4", description: "other")
29
+ product5 = create(:product, category: "category1", title: "other", description: "description")
30
+
31
+ ProductIndex.import [product1, product2, product3, product4, product5]
32
+
33
+ query = ProductIndex.aggregate(category: {}) do |aggregation|
34
+ aggregation
35
+ .where(title: ["title1", "title2", "title3", "title4"])
36
+ .where(description: ["description1", "description2", "description3"])
37
+ .aggregate(:category)
38
+ end
39
+
40
+ aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[:key]] = bucket.doc_count }
41
+
42
+ expect(aggregations).to eq("category1" => 2, "category2" => 1)
43
+ end
44
+
45
+ it "works with ranges" do
46
+ product1 = create(:product, category: "category1", title: "title1", price: 100)
47
+ product2 = create(:product, category: "category2", title: "title2", price: 150)
48
+ product3 = create(:product, category: "category1", title: "title3", price: 200)
49
+ product4 = create(:product, category: "category2", title: "title4", price: 250)
50
+ product5 = create(:product, category: "category1", title: "other", price: 200)
51
+
52
+ ProductIndex.import [product1, product2, product3, product4, product5]
53
+
54
+ query = ProductIndex.aggregate(category: {}) do |aggregation|
55
+ aggregation.where(title: "title1".."title3").where(price: 100..200).aggregate(:category)
56
+ end
57
+
58
+ aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[:key]] = bucket.doc_count }
59
+
60
+ expect(aggregations).to eq("category1" => 2, "category2" => 1)
61
+ end
62
+ end
63
+
64
+ describe "#where_not" do
65
+ it "sets up the constraints correctly for the aggregation and is chainable" do
66
+ product1 = create(:product, category: "category1", title: "title1")
67
+ product2 = create(:product, category: "category2", title: "title2")
68
+ product3 = create(:product, category: "category1", title: "title3")
69
+ product4 = create(:product, category: "category2", title: "title4")
70
+ product5 = create(:product, category: "category1", title: "title5")
71
+
72
+ ProductIndex.import [product1, product2, product3, product4, product5]
73
+
74
+ query = ProductIndex.aggregate(category: {}) do |aggregation|
75
+ aggregation.where_not(title: "title4").where_not(title: "title5").aggregate(:category)
76
+ end
77
+
78
+ aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[:key]] = bucket.doc_count }
79
+
80
+ expect(aggregations).to eq("category1" => 2, "category2" => 1)
81
+ end
82
+
83
+ it "works with arrays" do
84
+ product1 = create(:product, category: "category1", title: "title1")
85
+ product2 = create(:product, category: "category2", title: "title2")
86
+ product3 = create(:product, category: "category1", title: "title3")
87
+ product4 = create(:product, category: "category2", title: "title4")
88
+ product5 = create(:product, category: "category1", title: "title5")
89
+ product6 = create(:product, category: "category2", title: "title6")
90
+ product7 = create(:product, category: "category1", title: "title7")
91
+
92
+ ProductIndex.import [product1, product2, product3, product4, product5, product6, product7]
93
+
94
+ query = ProductIndex.aggregate(category: {}) do |aggregation|
95
+ aggregation.where_not(title: ["title1", "title2"]).where_not(title: ["title6", "title7"]).aggregate(:category)
96
+ end
97
+
98
+ aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[:key]] = bucket.doc_count }
99
+
100
+ expect(aggregations).to eq("category1" => 2, "category2" => 1)
101
+ end
102
+
103
+ it "works with ranges" do
104
+ product1 = create(:product, category: "category1", title: "title1", price: 100)
105
+ product2 = create(:product, category: "category2", title: "title2", price: 150)
106
+ product3 = create(:product, category: "category1", title: "title3", price: 200)
107
+ product4 = create(:product, category: "category2", title: "title4", price: 250)
108
+ product5 = create(:product, category: "category1", title: "title5", price: 300)
109
+ product6 = create(:product, category: "category2", title: "title6", price: 350)
110
+ product7 = create(:product, category: "category1", title: "title7", price: 400)
111
+
112
+ ProductIndex.import [product1, product2, product3, product4, product5, product6, product7]
113
+
114
+ query = ProductIndex.aggregate(category: {}) do |aggregation|
115
+ aggregation.where_not(price: 100..150).where_not(title: "title6".."title7").aggregate(:category)
116
+ end
117
+
118
+ aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[:key]] = bucket.doc_count }
119
+
120
+ expect(aggregations).to eq("category1" => 2, "category2" => 1)
121
+ end
122
+ end
123
+
124
+ describe "#filter" do
125
+ it "sets up the constraints correctly for the aggregation and is chainable" do
126
+ product1 = create(:product, category: "category1", title: "title", price: 100)
127
+ product2 = create(:product, category: "category2", title: "title", price: 150)
128
+ product3 = create(:product, category: "category1", title: "title", price: 200)
129
+ product4 = create(:product, category: "category2", title: "other", price: 200)
130
+ product5 = create(:product, category: "category1", title: "title", price: 250)
131
+
132
+ ProductIndex.import [product1, product2, product3, product4, product5]
133
+
134
+ query = ProductIndex.aggregate(category: {}) do |aggregation|
135
+ aggregation.filter(range: { price: { gte: 100, lte: 200 } }).filter(term: { title: "title" }).aggregate(:category)
136
+ end
137
+
138
+ aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[:key]] = bucket.doc_count }
139
+
140
+ expect(aggregations).to eq("category1" => 2, "category2" => 1)
141
+ end
142
+ end
143
+
144
+ describe "#range" do
145
+ it "sets up the constraints correctly for the aggregation and is chainable" do
146
+ product1 = create(:product, category: "category1", title: "title1", price: 100)
147
+ product2 = create(:product, category: "category2", title: "title2", price: 150)
148
+ product3 = create(:product, category: "category1", title: "title3", price: 200)
149
+ product4 = create(:product, category: "category2", title: "title4", price: 250)
150
+ product5 = create(:product, category: "category1", title: "title5", price: 300)
151
+ product6 = create(:product, category: "category2", title: "title6", price: 350)
152
+ product7 = create(:product, category: "category1", title: "title7", price: 400)
153
+
154
+ ProductIndex.import [product1, product2, product3, product4, product5, product6, product7]
155
+
156
+ query = ProductIndex.aggregate(category: {}) do |aggregation|
157
+ aggregation.range(:price, gte: 100, lte: 200).range(:title, gte: "title1", lte: "title3").aggregate(:category)
158
+ end
159
+
160
+ aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[:key]] = bucket.doc_count }
161
+
162
+ expect(aggregations).to eq("category1" => 2, "category2" => 1)
163
+ end
164
+ end
165
+
166
+ describe "#match_all" do
167
+ it "sets up the constraints correctly for the aggregation and is chainable" do
168
+ product1 = create(:product, category: "category1")
169
+ product2 = create(:product, category: "category2")
170
+ product3 = create(:product, category: "category1")
171
+
172
+ ProductIndex.import [product1, product2, product3]
173
+
174
+ query = ProductIndex.aggregate(category: {}) do |aggregation|
175
+ aggregation.match_all.aggregate(:category)
176
+ end
177
+
178
+ aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[:key]] = bucket.doc_count }
179
+
180
+ expect(aggregations).to eq("category1" => 2, "category2" => 1)
181
+ end
182
+ end
183
+
184
+ describe "#exists" do
185
+ it "sets up the constraints correctly for the aggregation and is chainable" do
186
+ product1 = create(:product, category: "category1", title: "title1", price: 10)
187
+ product2 = create(:product, category: "category2", title: "title2")
188
+ product3 = create(:product, category: "category1", title: "title3", price: 20)
189
+ product4 = create(:product, category: "category2", title: "title4", price: 30)
190
+ product5 = create(:product, category: "category1", price: 40)
191
+
192
+ ProductIndex.import [product1, product2, product3, product4, product5]
193
+
194
+ query = ProductIndex.aggregate(category: {}) do |aggregation|
195
+ aggregation.exists(:title).exists(:price).aggregate(:category)
196
+ end
197
+
198
+ aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[:key]] = bucket.doc_count }
199
+
200
+ expect(aggregations).to eq("category1" => 2, "category2" => 1)
201
+ end
202
+ end
203
+
204
+ describe "#exists_not" do
205
+ it "sets up the constraints correctly for the aggregation and is chainable" do
206
+ product1 = create(:product, category: "category1")
207
+ product2 = create(:product, category: "category2", title: "title2")
208
+ product3 = create(:product, category: "category1")
209
+ product4 = create(:product, category: "category2")
210
+ product5 = create(:product, category: "category1", price: 40)
211
+
212
+ ProductIndex.import [product1, product2, product3, product4, product5]
213
+
214
+ query = ProductIndex.aggregate(category: {}) do |aggregation|
215
+ aggregation.exists_not(:title).exists_not(:price).aggregate(:category)
216
+ end
217
+
218
+ aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[:key]] = bucket.doc_count }
219
+
220
+ expect(aggregations).to eq("category1" => 2, "category2" => 1)
221
+ end
222
+ end
223
+
224
+ describe "#aggregate" do
225
+ it "aggregates within an aggregation" do
226
+ product1 = create(:product, category: "category1", title: "title1", price: 10)
227
+ product2 = create(:product, category: "category1", title: "title2", price: 15)
228
+ product3 = create(:product, category: "category1", title: "title1", price: 20)
229
+ product4 = create(:product, category: "category2", title: "title2", price: 25)
230
+ product5 = create(:product, category: "category2", title: "title1", price: 30)
231
+ product6 = create(:product, category: "category2", title: "title2", price: 35)
232
+
233
+ ProductIndex.import [product1, product2, product3, product4, product5, product6]
234
+
235
+ query = ProductIndex.aggregate(:category) do |aggregation|
236
+ aggregation.aggregate(:title) do |aggregation2|
237
+ aggregation2.aggregate(price: { sum: { field: "price" } })
238
+ end
239
+ end
240
+
241
+ aggregations = query.aggregations(:category).each_with_object({}) do |(key, agg), hash|
242
+ hash[key] = agg.doc_count
243
+ end
244
+
245
+ expect(aggregations).to eq("category1" => 3, "category2" => 3)
246
+
247
+ aggregations = query.aggregations(:category)["category1"].title.buckets.each_with_object({}) do |bucket, hash|
248
+ hash[bucket[:key]] = bucket.doc_count
249
+ end
250
+
251
+ expect(aggregations).to eq("title1" => 2, "title2" => 1)
252
+
253
+ aggregations = query.aggregations(:category)["category2"].title.buckets.each_with_object({}) do |bucket, hash|
254
+ hash[bucket[:key]] = bucket.doc_count
255
+ end
256
+
257
+ expect(aggregations).to eq("title1" => 1, "title2" => 2)
258
+
259
+ expect(query.aggregations(:category)["category1"].title.buckets.detect { |bucket| bucket[:key] == "title1" }.price.value).to eq(30)
260
+ expect(query.aggregations(:category)["category1"].title.buckets.detect { |bucket| bucket[:key] == "title2" }.price.value).to eq(15)
261
+ expect(query.aggregations(:category)["category2"].title.buckets.detect { |bucket| bucket[:key] == "title1" }.price.value).to eq(30)
262
+ expect(query.aggregations(:category)["category2"].title.buckets.detect { |bucket| bucket[:key] == "title2" }.price.value).to eq(60)
263
+ end
264
+ end
265
+ end
@@ -0,0 +1,78 @@
1
+
2
+ require File.expand_path("../spec_helper", __dir__)
3
+
4
+ RSpec.describe SearchFlip::Bulk do
5
+ describe "#bulk" do
6
+ it "uses bulk mode" do
7
+ product1, product2 = create_list(:product, 2)
8
+
9
+ expect(ProductIndex.total_count).to eq(0)
10
+
11
+ ProductIndex.bulk do |bulk|
12
+ bulk.create product1.id, ProductIndex.serialize(product1)
13
+ bulk.create product2.id, ProductIndex.serialize(product1)
14
+ end
15
+
16
+ expect(ProductIndex.total_count).to eq(2)
17
+
18
+ ProductIndex.bulk do |bulk|
19
+ bulk.delete product1.id
20
+ bulk.delete product2.id
21
+ end
22
+
23
+ expect(ProductIndex.total_count).to eq(0)
24
+ end
25
+
26
+ it "accepts and passes options" do
27
+ product1, product2 = create_list(:product, 2)
28
+
29
+ ProductIndex.import [product1, product2]
30
+
31
+ block = lambda do
32
+ ProductIndex.bulk do |bulk|
33
+ bulk.create product1.id, ProductIndex.serialize(product1)
34
+ bulk.create product2.id, ProductIndex.serialize(product1)
35
+ end
36
+ end
37
+
38
+ expect(&block).to raise_error(SearchFlip::Bulk::Error)
39
+
40
+ ProductIndex.bulk(ignore_errors: [409]) do |bulk|
41
+ bulk.create product1.id, ProductIndex.serialize(product1)
42
+ bulk.create product2.id, ProductIndex.serialize(product1)
43
+ end
44
+ end
45
+
46
+ it "accepts and passes item options" do
47
+ product = create(:product)
48
+
49
+ ProductIndex.bulk do |bulk|
50
+ bulk.index product.id, ProductIndex.serialize(product), version: 1, version_type: "external_gt"
51
+ end
52
+
53
+ block = lambda do
54
+ ProductIndex.bulk do |bulk|
55
+ bulk.index product.id, ProductIndex.serialize(product), version: 1, version_type: "external_gt"
56
+ end
57
+ end
58
+
59
+ expect(&block).to raise_error(SearchFlip::Bulk::Error)
60
+ end
61
+
62
+ it "uses the specified http_client" do
63
+ product = create(:product)
64
+
65
+ stub_request(:put, "#{ProductIndex.type_url}/_bulk?filter_path=errors")
66
+ .with(headers: { "X-Header" => "Value" })
67
+ .to_return(status: 500)
68
+
69
+ block = lambda do
70
+ ProductIndex.bulk http_client: ProductIndex.connection.http_client.headers("X-Header" => "Value") do |bulk|
71
+ bulk.index product.id, ProductIndex.serialize(product)
72
+ end
73
+ end
74
+
75
+ expect(&block).to raise_error(SearchFlip::ResponseError)
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,211 @@
1
+
2
+ require File.expand_path("../spec_helper", __dir__)
3
+
4
+ RSpec.describe SearchFlip::Connection do
5
+ describe "#base_url" do
6
+ it "returns the correct url" do
7
+ expect(SearchFlip::Connection.new(base_url: "base url").base_url).to eq("base url")
8
+ end
9
+ end
10
+
11
+ describe "#msearch" do
12
+ it "sends multiple queries and returns all responses" do
13
+ ProductIndex.import create(:product)
14
+ CommentIndex.import create(:comment)
15
+
16
+ responses = SearchFlip::Connection.new.msearch([ProductIndex.match_all, CommentIndex.match_all])
17
+
18
+ expect(responses.size).to eq(2)
19
+ expect(responses[0].total_entries).to eq(1)
20
+ expect(responses[1].total_entries).to eq(1)
21
+ end
22
+ end
23
+
24
+ describe "#update_aliases" do
25
+ it "changes the aliases" do
26
+ connection = SearchFlip::Connection.new
27
+
28
+ connection.update_aliases(actions: [add: { index: "products", alias: "alias1" }])
29
+ expect(connection.get_aliases(alias_name: "alias1").keys).to eq(["products"])
30
+
31
+ connection.update_aliases(actions: [remove: { index: "products", alias: "alias1" }])
32
+ expect(connection.alias_exists?("alias1")).to eq(false)
33
+ end
34
+ end
35
+
36
+ describe "#get_aliases" do
37
+ it "returns the specified aliases" do
38
+ begin
39
+ connection = SearchFlip::Connection.new
40
+
41
+ connection.update_aliases(actions: [
42
+ { add: { index: "comments", alias: "alias1" } },
43
+ { add: { index: "products", alias: "alias2" } },
44
+ { add: { index: "products", alias: "alias3" } }
45
+ ])
46
+
47
+ expect(connection.get_aliases.keys.to_set).to eq(["comments", "products"].to_set)
48
+ expect(connection.get_aliases["products"]["aliases"].keys.to_set).to eq(["alias2", "alias3"].to_set)
49
+ expect(connection.get_aliases["comments"]["aliases"].keys).to eq(["alias1"])
50
+ expect(connection.get_aliases(index_name: "products").keys).to eq(["products"])
51
+ expect(connection.get_aliases(index_name: "comments,products").keys.to_set).to eq(["comments", "products"].to_set)
52
+ expect(connection.get_aliases(alias_name: "alias1,alias2").keys.to_set).to eq(["comments", "products"].to_set)
53
+ expect(connection.get_aliases(alias_name: "alias1,alias2")["products"]["aliases"].keys).to eq(["alias2"])
54
+ ensure
55
+ connection.update_aliases(actions: [
56
+ { remove: { index: "comments", alias: "alias1" } },
57
+ { remove: { index: "products", alias: "alias2" } },
58
+ { remove: { index: "products", alias: "alias3" } }
59
+ ])
60
+ end
61
+ end
62
+ end
63
+
64
+ describe "#alias_exists?" do
65
+ it "returns whether or not the specified alias exists?" do
66
+ begin
67
+ connection = SearchFlip::Connection.new
68
+
69
+ expect(connection.alias_exists?(:some_alias)).to eq(false)
70
+
71
+ connection.update_aliases(actions: [add: { index: "products", alias: "some_alias" }])
72
+
73
+ expect(connection.alias_exists?(:some_alias)).to eq(true)
74
+ ensure
75
+ connection.update_aliases(actions: [remove: { index: "products", alias: "some_alias" }])
76
+ end
77
+ end
78
+ end
79
+
80
+ describe "#get_indices" do
81
+ it "returns the specified indices" do
82
+ connection = SearchFlip::Connection.new
83
+
84
+ expect(connection.get_indices.map { |index| index["index"] }.to_set).to eq(["comments", "products"].to_set)
85
+ expect(connection.get_indices("com*").map { |index| index["index"] }).to eq(["comments"])
86
+ end
87
+ end
88
+
89
+ describe "#create_index" do
90
+ it "creates the specified index" do
91
+ begin
92
+ connection = SearchFlip::Connection.new
93
+
94
+ expect(connection.index_exists?("index_name")).to eq(false)
95
+
96
+ connection.create_index("index_name")
97
+
98
+ expect(connection.index_exists?("index_name")).to eq(true)
99
+ ensure
100
+ connection.delete_index("index_name") if connection.index_exists?("index_name")
101
+ end
102
+ end
103
+
104
+ it "respects a payload" do
105
+ connection = SearchFlip::Connection.new
106
+
107
+ connection.create_index("index_name", settings: { number_of_shards: 3 })
108
+
109
+ expect(connection.get_index_settings("index_name")["index_name"]["settings"]["index"]["number_of_shards"]).to eq("3")
110
+ ensure
111
+ connection.delete_index("index_name") if connection.index_exists?("index_name")
112
+ end
113
+ end
114
+
115
+ describe "#update_index_settings" do
116
+ it "updates the index settings" do
117
+ begin
118
+ connection = SearchFlip::Connection.new
119
+
120
+ connection.create_index("index_name")
121
+ connection.update_index_settings("index_name", settings: { number_of_replicas: 3 })
122
+
123
+ expect(connection.get_index_settings("index_name")["index_name"]["settings"]["index"]["number_of_replicas"]).to eq("3")
124
+ ensure
125
+ connection.delete_index("index_name") if connection.index_exists?("index_name")
126
+ end
127
+ end
128
+ end
129
+
130
+ describe "#get_index_settings" do
131
+ it "fetches the index settings" do
132
+ begin
133
+ connection = SearchFlip::Connection.new
134
+
135
+ connection.create_index("index_name", settings: { number_of_shards: 3 })
136
+
137
+ expect(connection.get_index_settings("index_name")["index_name"]["settings"]["index"]["number_of_shards"]).to eq("3")
138
+ ensure
139
+ connection.delete_index("index_name") if connection.index_exists?("index_name")
140
+ end
141
+ end
142
+ end
143
+
144
+ describe "#update_mapping" do
145
+ it "updates the mapping of an index" do
146
+ begin
147
+ connection = SearchFlip::Connection.new
148
+
149
+ mapping = { "type_name" => { "properties" => { "id" => { "type" => "long" } } } }
150
+
151
+ connection.create_index("index_name")
152
+ connection.update_mapping("index_name", "type_name", mapping)
153
+
154
+ expect(connection.get_mapping("index_name", "type_name")).to eq("index_name" => { "mappings" => mapping })
155
+ ensure
156
+ connection.delete_index("index_name") if connection.index_exists?("index_name")
157
+ end
158
+ end
159
+ end
160
+
161
+ describe "#delete_index" do
162
+ it "deletes the specified index" do
163
+ begin
164
+ connection = SearchFlip::Connection.new
165
+
166
+ connection.create_index("index_name")
167
+ expect(connection.index_exists?("index_name")).to eq(true)
168
+
169
+ connection.delete_index("index_name")
170
+ expect(connection.index_exists?("index_name")).to eq(false)
171
+ ensure
172
+ connection.delete_index("index_name") if connection.index_exists?("index_name")
173
+ end
174
+ end
175
+ end
176
+
177
+ describe "#refresh" do
178
+ it "refreshes all or the specified indices" do
179
+ begin
180
+ connection = SearchFlip::Connection.new
181
+
182
+ connection.create_index("index1")
183
+ connection.create_index("index2")
184
+
185
+ expect(connection.refresh).to be_truthy
186
+ expect(connection.refresh("index1")).to be_truthy
187
+ expect(connection.refresh(["index1", "index2"])).to be_truthy
188
+ ensure
189
+ connection.delete_index("index1") if connection.index_exists?("index1")
190
+ connection.delete_index("index2") if connection.index_exists?("index2")
191
+ end
192
+ end
193
+ end
194
+
195
+ describe "#index_url" do
196
+ it "returns the index url for the specified index" do
197
+ connection = SearchFlip::Connection.new(base_url: "base_url")
198
+
199
+ expect(connection.index_url("index_name")).to eq("base_url/index_name")
200
+ end
201
+ end
202
+
203
+ describe "#type_url" do
204
+ it "returns the type url for the specified index and type" do
205
+ connection = SearchFlip::Connection.new(base_url: "base_url")
206
+
207
+ expect(connection.type_url("index_name", "type_name")).to eq("base_url/index_name/type_name")
208
+ end
209
+ end
210
+ end
211
+