1# frozen_string_literal: true
2
3require "test_helper"
4require "tel_selections"
5
6class TelSelectionsTest < Minitest::Test
7 def setup
8 @manager = TelSelections.new(
9 redis: FakeRedis.new,
10 db: FakeDB.new,
11 memcache: FakeMemcache.new
12 )
13 end
14
15 def test_set_get
16 assert_kind_of TelSelections::ChooseTel, @manager["jid@example.com"].sync
17 @manager.set(
18 "jid@example.com",
19 TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
20 ).sync
21 assert_kind_of TelSelections::HaveTel, @manager["jid@example.com"].sync
22 end
23 em :test_set_get
24
25 def test_choose_tel_have_tel
26 jid = "jid@example.com"
27 @manager.set(
28 jid,
29 TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
30 ).sync
31 assert_equal(
32 "+15555550000",
33 @manager[jid].then(&:choose_tel_or_data).sync.tel
34 )
35 end
36 em :test_choose_tel_have_tel
37
38 class AvailableNumberTest < Minitest::Test
39 def test_for_no_rsm
40 form = Blather::Stanza::X.new
41 form.fields = [{ var: "q", value: "226" }]
42 iris_query = TelSelections::ChooseTel::AvailableNumber
43 .for(form, db: FakeDB.new, memcache: FakeMemcache.new)
44 .instance_variable_get(:@iris_query)
45 assert_equal(
46 { areaCode: "226", enableTNDetail: true, LCA: false, quantity: 10 },
47 iris_query
48 )
49 end
50
51 def test_for_rsm
52 form = Blather::Stanza::X.new
53 form.fields = [{ var: "q", value: "226" }]
54 Nokogiri::XML::Builder.with(form) do
55 set(xmlns: "http://jabber.org/protocol/rsm") do
56 max 500
57 end
58 end
59 iris_query = TelSelections::ChooseTel::AvailableNumber
60 .for(form, db: FakeDB.new, memcache: FakeMemcache.new)
61 .instance_variable_get(:@iris_query)
62 # quantity should be 500 due to max inside tel selections
63 assert_equal(
64 { areaCode: "226", enableTNDetail: true, LCA: false, quantity: 500 },
65 iris_query
66 )
67 end
68
69 def test_for_feelinglucky
70 form = Blather::Stanza::X.new
71 form.fields = [
72 { var: "q", value: "" },
73 {
74 var: "http://jabber.org/protocol/commands#actions",
75 value: "feelinglucky"
76 }
77 ]
78 iris_query = TelSelections::ChooseTel::AvailableNumber
79 .for(form, db: FakeDB.new, memcache: FakeMemcache.new)
80 .instance_variable_get(:@iris_query)
81 assert_equal(
82 { areaCode: "810", enableTNDetail: true, LCA: false, quantity: 10 },
83 iris_query
84 )
85 end
86
87 def test_fallback
88 stub_request(
89 :get,
90 "https://dashboard.bandwidth.com/v1.0/accounts//availableNumbers" \
91 "?city=Kitchener-Waterloo&enableTNDetail=true&lCA=false&" \
92 "quantity=10&state=ON"
93 ).to_return(status: 200, body: "")
94
95 stub_request(
96 :get,
97 "https://geocoder.ca/?json=1&locate=Kitchener-Waterloo,%20ON"
98 ).to_return(status: 200, body: {
99 postal: "N2H", longt: 0, latt: 0
100 }.to_json)
101
102 stub_request(
103 :get,
104 "https://dashboard.bandwidth.com/v1.0/accounts//availableNumbers" \
105 "?areaCode=226&enableTNDetail=true&quantity=10"
106 ).to_return(status: 200, body: <<~XML)
107 <SearchResult>
108 <TelephoneNumberList>
109 <TelephoneNumber>
110 <FullNumber>22655512345</FullNumber>
111 <City>Somewhere</City>
112 <State>ON</State>
113 </TelephoneNumber>
114 </TelephoneNumberList>
115 </SearchResult>
116 XML
117
118 db = FakeDB.new(
119 ["CA", "POINT(0.0000000000 0.0000000000)", 3] =>
120 [{ "area_code" => "226" }]
121 )
122 form = Blather::Stanza::X.new
123 form.fields = [{ var: "q", value: "Kitchener, ON" }]
124 tns = execute_command do
125 TelSelections::ChooseTel::AvailableNumber
126 .for(form, db: db, memcache: FakeMemcache.new)
127 .tns
128 end
129 assert_equal(
130 ["(226) 555-12345 (Somewhere, ON)"],
131 tns.map(&:to_s)
132 )
133 end
134 em :test_fallback
135
136 def test_local_inventory
137 stub_request(
138 :get,
139 "https://dashboard.bandwidth.com/v1.0/accounts//availableNumbers" \
140 "?city=Kitchener-Waterloo&enableTNDetail=true&lCA=false&" \
141 "quantity=10&state=ON"
142 ).to_return(status: 200, body: "")
143
144 db = FakeDB.new(
145 ["ON", "Kitchener-Waterloo"] => [{
146 "tel" => "+122655512345",
147 "region" => "ON",
148 "locality" => "Kitchener-Waterloo"
149 }]
150 )
151 form = Blather::Stanza::X.new
152 form.fields = [{ var: "q", value: "Kitchener, ON" }]
153 tns = execute_command do
154 TelSelections::ChooseTel::AvailableNumber
155 .for(form, db: db, memcache: FakeMemcache.new)
156 .tns
157 end
158 assert_equal(
159 ["(226) 555-12345 (Kitchener-Waterloo, ON)"],
160 tns.map(&:to_s)
161 )
162 end
163 em :test_local_inventory
164 end
165
166 class TnOptionTest < Minitest::Test
167 def setup
168 @tn = TelSelections::ChooseTel::Tn::Option.new(
169 full_number: "5551234567",
170 city: "Toronto",
171 state: "ON",
172 garbage: "stuff"
173 )
174 @local_tel = TelSelections::ChooseTel::Tn::LocalInventory.new(
175 @tn,
176 "test_account",
177 price: 10.0
178 )
179 end
180
181 def test_to_s
182 assert_equal "(555) 123-4567 (Toronto, ON)", @tn.to_s
183 end
184
185 def test_tel
186 assert_equal "+15551234567", @tn.tel
187 end
188
189 def test_option
190 assert_equal(
191 Blather::Stanza::X::Field::Option.new(
192 label: "(555) 123-4567 (Toronto, ON)",
193 value: "+15551234567"
194 ),
195 @tn.option
196 )
197 end
198
199 def test_option_positive_price
200 assert_equal(
201 Blather::Stanza::X::Field::Option.new(
202 label: "(555) 123-4567 (Toronto, ON) +$10.00",
203 value: "+15551234567"
204 ),
205 @local_tel.option
206 )
207 end
208
209 def test_option_reference
210 ref = @tn.option.find("ns:reference", ns: "urn:xmpp:reference:0").first
211 assert_equal(
212 @tn.formatted_tel,
213 @tn.option.label[ref["begin"].to_i..ref["end"].to_i]
214 )
215 assert_equal "tel:+15551234567", ref["uri"]
216 end
217 end
218
219 class QTest < Minitest::Test
220 def test_for_area_code
221 q = TelSelections::ChooseTel::Q.for("226")
222 assert_equal({ areaCode: "226" }, q.iris_query)
223 end
224
225 def test_for_area_code_sql
226 q = TelSelections::ChooseTel::Q.for("226")
227 assert_equal(
228 [
229 "SELECT * FROM tel_inventory " \
230 "WHERE available_after < LOCALTIMESTAMP AND tel LIKE $1 " \
231 "AND source NOT LIKE 'xmpp:%'",
232 "+1226%"
233 ],
234 q.sql_query
235 )
236 end
237
238 def test_for_npanxx
239 q = TelSelections::ChooseTel::Q.for("226666")
240 assert_equal({ npaNxx: "226666" }, q.iris_query)
241 end
242
243 def test_for_npanxx_sql
244 q = TelSelections::ChooseTel::Q.for("226666")
245 assert_equal(
246 [
247 "SELECT * FROM tel_inventory " \
248 "WHERE available_after < LOCALTIMESTAMP AND tel LIKE $1 " \
249 "AND source NOT LIKE 'xmpp:%'",
250 "+1226666%"
251 ],
252 q.sql_query
253 )
254 end
255
256 def test_for_npanxxx
257 q = TelSelections::ChooseTel::Q.for("2266667")
258 assert_equal({ npaNxxx: "2266667" }, q.iris_query)
259 end
260
261 def test_for_npanxxx_sql
262 q = TelSelections::ChooseTel::Q.for("2266667")
263 assert_equal(
264 [
265 "SELECT * FROM tel_inventory " \
266 "WHERE available_after < LOCALTIMESTAMP AND tel LIKE $1 "\
267 "AND source NOT LIKE 'xmpp:%'",
268 "+12266667%"
269 ],
270 q.sql_query
271 )
272 end
273
274 def test_for_zip
275 q = TelSelections::ChooseTel::Q.for("90210")
276 assert_equal({ zip: "90210" }, q.iris_query)
277 end
278
279 def test_for_zip_sql
280 q = TelSelections::ChooseTel::Q.for("90210")
281 refute q.sql_query
282 end
283
284 def test_for_localvanity
285 q = TelSelections::ChooseTel::Q.for("~mboa")
286 assert_equal({ localVanity: "mboa" }, q.iris_query)
287 end
288
289 def test_for_localvanity_sql
290 q = TelSelections::ChooseTel::Q.for("~mboa")
291 assert_equal(
292 [
293 "SELECT * FROM tel_inventory " \
294 "WHERE available_after < LOCALTIMESTAMP AND tel LIKE $1 " \
295 "AND source NOT LIKE 'xmpp:%'",
296 "%6262%"
297 ],
298 q.sql_query
299 )
300 end
301
302 def test_for_state
303 q = TelSelections::ChooseTel::Q.for("ON")
304 assert_equal({ state: "ON" }, q.iris_query)
305 end
306
307 def test_for_state_sql
308 q = TelSelections::ChooseTel::Q.for("ON")
309 assert_equal(
310 [
311 "SELECT * FROM tel_inventory " \
312 "WHERE available_after < LOCALTIMESTAMP AND region = $1 " \
313 "AND source NOT LIKE 'xmpp:%'",
314 "ON"
315 ],
316 q.sql_query
317 )
318 end
319
320 def test_for_state_name
321 q = TelSelections::ChooseTel::Q.for("ontario")
322 assert_equal({ state: "ON" }, q.iris_query)
323 end
324
325 def test_for_state_name_sql
326 q = TelSelections::ChooseTel::Q.for("ontario")
327 assert_equal(
328 [
329 "SELECT * FROM tel_inventory " \
330 "WHERE available_after < LOCALTIMESTAMP AND region = $1 " \
331 "AND source NOT LIKE 'xmpp:%'",
332 "ON"
333 ],
334 q.sql_query
335 )
336 end
337
338 def test_for_new_york
339 q = TelSelections::ChooseTel::Q.for("New York")
340 assert_equal({ state: "NY" }, q.iris_query)
341 end
342
343 def test_for_new_york_sql
344 q = TelSelections::ChooseTel::Q.for("New York")
345 assert_equal(
346 [
347 "SELECT * FROM tel_inventory " \
348 "WHERE available_after < LOCALTIMESTAMP AND region = $1 " \
349 "AND source NOT LIKE 'xmpp:%'",
350 "NY"
351 ],
352 q.sql_query
353 )
354 end
355
356 def test_for_new_york_ny
357 q = TelSelections::ChooseTel::Q.for(
358 "New York, NY",
359 db: FakeDB.new,
360 memcache: FakeMemcache.new
361 )
362 assert_equal({ city: "New York City", state: "NY" }, q.iris_query)
363 end
364
365 def test_for_new_york_ny_sql
366 q = TelSelections::ChooseTel::Q.for(
367 "New York, NY",
368 db: FakeDB.new,
369 memcache: FakeMemcache.new
370 )
371 assert_equal(
372 [
373 "SELECT * FROM tel_inventory " \
374 "WHERE available_after < LOCALTIMESTAMP " \
375 "AND region = $1 AND locality = $2 " \
376 "AND source NOT LIKE 'xmpp:%'",
377 "NY", "New York City"
378 ],
379 q.sql_query
380 )
381 end
382
383 def test_for_new_york_new_york
384 q = TelSelections::ChooseTel::Q.for(
385 "New York, New York",
386 db: FakeDB.new,
387 memcache: FakeMemcache.new
388 )
389 assert_equal({ city: "New York City", state: "NY" }, q.iris_query)
390 end
391
392 def test_for_new_york_new_york_sql
393 q = TelSelections::ChooseTel::Q.for(
394 "New York, New York",
395 db: FakeDB.new,
396 memcache: FakeMemcache.new
397 )
398 assert_equal(
399 [
400 "SELECT * FROM tel_inventory " \
401 "WHERE available_after < LOCALTIMESTAMP " \
402 "AND region = $1 AND locality = $2 " \
403 "AND source NOT LIKE 'xmpp:%'",
404 "NY", "New York City"
405 ],
406 q.sql_query
407 )
408 end
409
410 def test_for_citystate
411 q = TelSelections::ChooseTel::Q.for(
412 "Toronto, ON",
413 db: FakeDB.new,
414 memcache: FakeMemcache.new
415 )
416 assert_equal({ city: "Toronto", state: "ON" }, q.iris_query)
417 end
418
419 def test_for_citystate_sql
420 q = TelSelections::ChooseTel::Q.for(
421 "Toronto, ON",
422 db: FakeDB.new,
423 memcache: FakeMemcache.new
424 )
425 assert_equal(
426 [
427 "SELECT * FROM tel_inventory " \
428 "WHERE available_after < LOCALTIMESTAMP " \
429 "AND region = $1 AND locality = $2 " \
430 "AND source NOT LIKE 'xmpp:%'",
431 "ON", "Toronto"
432 ],
433 q.sql_query
434 )
435 end
436
437 def test_for_citystate_name
438 q = TelSelections::ChooseTel::Q.for(
439 "Toronto, Ontario",
440 db: FakeDB.new,
441 memcache: FakeMemcache.new
442 )
443 assert_equal({ city: "Toronto", state: "ON" }, q.iris_query)
444 end
445
446 def test_for_citystate_name_sql
447 q = TelSelections::ChooseTel::Q.for(
448 "Toronto, Ontario",
449 db: FakeDB.new,
450 memcache: FakeMemcache.new
451 )
452 assert_equal(
453 [
454 "SELECT * FROM tel_inventory " \
455 "WHERE available_after < LOCALTIMESTAMP " \
456 "AND region = $1 AND locality = $2 " \
457 "AND source NOT LIKE 'xmpp:%'",
458 "ON", "Toronto"
459 ],
460 q.sql_query
461 )
462 end
463
464 def test_for_garbage
465 assert_raises { TelSelections::ChooseTel::Q.for("garbage") }
466 end
467 end
468end