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