test_admin_command.rb

  1# frozen_string_literal: true
  2
  3require "test_helper"
  4require "admin_command"
  5require "admin_action"
  6
  7BackendSgx::IQ_MANAGER = Minitest::Mock.new
  8AdminAction::LaunchSnikket::IQ_MANAGER = Minitest::Mock.new
  9Customer::BLATHER = Minitest::Mock.new
 10AdminActionRepo::REDIS = Minitest::Mock.new
 11TrivialBackendSgxRepo::REDIS = Minitest::Mock.new
 12BandwidthTnRepo::DB = Minitest::Mock.new
 13AdminAction::NumberChange::REDIS = Minitest::Mock.new
 14
 15class AdminCommandTest < Minitest::Test
 16	def assert_undoable_form(iq, note_type=nil, note_text=nil)
 17		assert_equal :form, iq.form.type
 18		[:execute, :next, :complete].each do |action|
 19			assert iq.allowed_actions.include?(action)
 20		end
 21		assert_equal iq.note_type, note_type if note_type
 22
 23		assert iq.note_text = note_text if note_text
 24	end
 25
 26	def admin_command(tel="+15556667777", registered: OpenStruct.new(phone: tel))
 27		sgx = Minitest::Mock.new(OpenStruct.new(
 28			registered?: registered
 29		))
 30		[
 31			sgx,
 32			AdminCommand.new(
 33				customer(sgx: sgx),
 34				CustomerRepo.new(db: FakeDB.new),
 35				AdminActionRepo.new,
 36				Snikket::Repo.new(db: FakeDB.new)
 37			)
 38		]
 39	end
 40
 41	def test_no_user
 42		q_form = Blather::Stanza::Iq::Command.new
 43		q_form.action = :complete
 44		q_form.form.fields = [
 45			{ var: "q", value: "testuser" }
 46		]
 47
 48		customer_repo = Minitest::Mock.new
 49
 50		result = execute_command {
 51			customer_repo.expect(
 52				:find_by_format,
 53				EMPromise.resolve(OpenStruct.new(
 54					customer_id: "testuser",
 55					billing_customer_id: "testuser",
 56					balance: 0.to_d,
 57					jid: Blather::JID.new("test@example.com"),
 58					tndetails: {}
 59				)),
 60				["testuser"]
 61			)
 62
 63			customer_repo.expect(
 64				:find_by_format,
 65				EMPromise.resolve(nil),
 66				[Blather::JID]
 67			)
 68
 69			customer_repo.expect(
 70				:find_by_format,
 71				EMPromise.resolve(nil),
 72				[ProxiedJID]
 73			)
 74
 75			TrivialBackendSgxRepo::REDIS.expect(
 76				:get,
 77				EMPromise.resolve(nil),
 78				["jmp_customer_backend_sgx-testuser"]
 79			)
 80
 81			TrustLevelRepo::REDIS.expect(
 82				:get,
 83				EMPromise.resolve("Customer"),
 84				["jmp_customer_trust_level-testuser"]
 85			)
 86
 87			TrustLevelRepo::DB.expect(
 88				:query_one,
 89				EMPromise.resolve({ settled_amount: 0 }),
 90				[String, "testuser"], default: {}
 91			)
 92
 93			Subaccount::DB.expect(
 94				:query_defer,
 95				EMPromise.resolve([]),
 96				[String, ["testuser"]]
 97			)
 98
 99			Command::COMMAND_MANAGER.expect(
100				:write,
101				EMPromise.resolve(q_form),
102				[Matching.new do |iq|
103					assert_equal :form, iq.form.type
104					assert iq.form.field("q")
105				end]
106			)
107
108			AdminCommand.for(nil, customer_repo).start.catch { |e| e }
109		}
110
111		assert result.stanza.completed?
112		assert_mock customer_repo
113		assert_mock Command::COMMAND_MANAGER
114		assert_mock TrustLevelRepo::REDIS
115		assert_mock Subaccount::DB
116		assert_mock TrivialBackendSgxRepo::REDIS
117	end
118	em :test_no_user
119
120	def test_action_launch_snikket
121		sgx, admin = admin_command
122		domain_form = Blather::Stanza::Iq::Command.new
123		domain_form.form.fields = [
124			{ var: "domain", value: "test.snikket.chat" }
125		]
126
127		launched = Snikket::Launched.new
128		launched << Niceogiri::XML::Node.new(
129			:launched, launched.document, "xmpp:snikket.org/hosting/v1"
130		).tap { |inner|
131			inner << Niceogiri::XML::Node.new(
132				:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
133			).tap { |id|
134				id.content = "si-1234"
135			}
136			inner << Niceogiri::XML::Node.new(
137				:bootstrap, launched.document, "xmpp:snikket.org/hosting/v1"
138			).tap { |bootstrap|
139				bootstrap << Niceogiri::XML::Node.new(
140					:token, launched.document, "xmpp:snikket.org/hosting/v1"
141				).tap { |token|
142					token.content = "TOKEN"
143				}
144			}
145		}
146
147		result = execute_command {
148			Command::COMMAND_MANAGER.expect(
149				:write,
150				EMPromise.resolve(domain_form),
151				[Matching.new do |iq|
152					assert_equal :form, iq.form.type
153					assert iq.form.field("domain")
154				end]
155			)
156			Command::COMMAND_MANAGER.expect(
157				:write,
158				EMPromise.reject(:test_result),
159				[Matching.new do |iq|
160					assert :result, iq.type
161					assert(
162						"https://test.snikket.chat/invites_bootstrap?token=TOKEN",
163						iq.form.field("bootstrap-uri").value
164					)
165				end]
166			)
167
168			AdminAction::LaunchSnikket::IQ_MANAGER.expect(
169				:write,
170				EMPromise.resolve(launched),
171				[Matching.new do |iq|
172					assert_equal :set, iq.type
173					assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
174					assert_equal(
175						"test.snikket.chat",
176						iq.xpath(
177							"./ns:launch/ns:domain",
178							ns: "xmpp:snikket.org/hosting/v1"
179						).text
180					)
181				end]
182			)
183
184			admin.action_launch_snikket.catch { |e| e }
185		}
186
187		assert_equal :test_result, result
188		assert_mock sgx
189		assert_mock AdminAction::LaunchSnikket::IQ_MANAGER
190		assert_mock Customer::BLATHER
191	end
192	em :test_action_launch_snikket
193
194	def test_action_cancel_account
195		req = stub_request(:post, "https://api.churnbuster.io/v1/cancellations")
196			.with(
197				body: {
198					customer: {
199						source: "braintree",
200						source_id: "test",
201						email: "test@smtp.cheogram.com",
202						properties: {}
203					},
204					subscription: {
205						source: "braintree",
206						source_id: "test"
207					}
208				}.to_json
209			)
210			.to_return(status: 200, body: "", headers: {})
211
212		sgx, admin = admin_command
213
214		Customer::BLATHER.expect(
215			:<<,
216			EMPromise.resolve(nil),
217			[
218				Matching.new do |m|
219					assert_equal "Your JMP account has been cancelled.", m.body
220					assert_equal "test@example.net", m.to.to_s
221					assert_equal "notify_from@component", m.from.to_s
222				end
223			]
224		)
225
226		Customer::BLATHER.expect(
227			:<<,
228			EMPromise.resolve(nil),
229			[
230				Matching.new do |iq|
231					assert iq.remove?
232					assert_equal "test@example.net", iq.to.to_s
233					assert_equal "component", iq.from.to_s
234				end
235			]
236		)
237
238		sgx.expect(:deregister!, EMPromise.resolve(nil))
239
240		stub_request(
241			:post,
242			"https://dashboard.bandwidth.com/v1.0/accounts//disconnects"
243		).with(
244			body: {
245				name: "test",
246				DisconnectTelephoneNumberOrderType: {
247					TelephoneNumberList: {
248						TelephoneNumber: "5556667777"
249					}
250				}
251			}.to_xml(indent: 0, root: "DisconnectTelephoneNumberOrder")
252		).to_return(status: 200, body: "")
253
254		admin.action_cancel_account.sync
255
256		assert_mock sgx
257		assert_mock BackendSgx::IQ_MANAGER
258		assert_mock Customer::BLATHER
259		assert_requested req
260	end
261	em :test_action_cancel_account
262
263	def test_action_cancel_account_keep_number
264		rate_center_response = {
265			"TelephoneNumberDetails": {
266				State: "NY",
267				RateCenter: "NWYRCYZN01"
268			}
269		}.to_xml(indent: 0, root: "TelephoneNumberResponse")
270
271		bandwidth_req = stub_request(
272			:get,
273			"https://dashboard.bandwidth.com/v1.0/tns/5566667777/ratecenter"
274		)
275			.with(
276				headers: {
277					"Accept" => "application/xml",
278					"Accept-Encoding" => "gzip, compressed",
279					"Authorization" => "Basic dGVzdF9id191c2VyOnRlc3RfYndfcGFzc3dvcmQ=",
280					"User-Agent" => "Ruby-Bandwidth-Iris"
281				},
282				body: ""
283			)
284			.to_return(status: 200, body: rate_center_response, headers: {})
285
286		churnbuster_req = stub_request(
287			:post,
288			"https://api.churnbuster.io/v1/cancellations"
289		)
290			.with(
291				body: {
292					customer: {
293						source: "braintree",
294						source_id: "test",
295						email: "test@smtp.cheogram.com",
296						properties: {}
297					},
298					subscription: {
299						source: "braintree",
300						source_id: "test"
301					}
302				}.to_json
303			)
304			.to_return(status: 200, body: "", headers: {})
305
306		sgx, admin = admin_command("+15566667777")
307
308		sql_params = ["+15566667777", "NY", "NWYRCYZN01", "test_bw_account"]
309
310		BandwidthTnRepo::DB.expect(
311			:exec,
312			EMPromise.resolve(nil),
313			[String, sql_params]
314		)
315
316		Customer::BLATHER.expect(
317			:<<,
318			EMPromise.resolve(nil),
319			[
320				Matching.new do |m|
321					assert_equal "Your JMP account has been cancelled.", m.body
322					assert_equal "test@example.net", m.to.to_s
323					assert_equal "notify_from@component", m.from.to_s
324				end
325			]
326		)
327
328		Customer::BLATHER.expect(
329			:<<,
330			EMPromise.resolve(nil),
331			[
332				Matching.new do |iq|
333					assert iq.remove?
334					assert_equal "test@example.net", iq.to.to_s
335					assert_equal "component", iq.from.to_s
336				end
337			]
338		)
339
340		sgx.expect(:deregister!, EMPromise.resolve(nil))
341
342		admin.action_cancel_account.sync
343
344		assert_mock sgx
345		assert_mock BackendSgx::IQ_MANAGER
346		assert_mock Customer::BLATHER
347		assert_mock BandwidthTnRepo::DB
348
349		assert_requested churnbuster_req
350		assert_requested bandwidth_req
351	end
352	em :test_action_cancel_account_keep_number
353
354	def test_change_num_for_unregistered_customer
355		_sgx, admin = admin_command(registered: false)
356
357		error =
358			assert_raises("number_change should have raised") {
359				admin.action_number_change.sync
360			}
361
362		assert_equal "Customer not registered", error.message
363
364		assert_mock BackendSgx::IQ_MANAGER
365		assert_mock Customer::BLATHER
366		assert_mock BandwidthTnRepo::DB
367	end
368	em :test_change_num_for_unregistered_customer
369end