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