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
   8BackendSgx::REDIS = Minitest::Mock.new
   9AdminAction::LaunchSnikket::IQ_MANAGER = Minitest::Mock.new
  10Customer::BLATHER = Minitest::Mock.new
  11AdminActionRepo::REDIS = Minitest::Mock.new
  12TrivialBackendSgxRepo::REDIS = Minitest::Mock.new
  13BandwidthTnRepo::DB = Minitest::Mock.new
  14AdminAction::NumberChange::REDIS = Minitest::Mock.new
  15
  16class AdminCommandTest < Minitest::Test
  17	def assert_undoable_form(iq, note_type=nil, note_text=nil)
  18		assert_equal :form, iq.form.type
  19		[:execute, :next, :complete].each do |action|
  20			assert iq.allowed_actions.include?(action)
  21		end
  22		assert_equal iq.note_type, note_type if note_type
  23
  24		assert iq.note_text = note_text if note_text
  25	end
  26
  27	def assert_change_number_form(iq)
  28		assert_equal(
  29			iq.form.field("new_tel")&.type,
  30			"text-single"
  31		)
  32		assert_equal(
  33			iq.form.field("new_backend")&.type,
  34			"list-single"
  35		)
  36		assert_equal(
  37			iq.form.field("should_delete")&.type,
  38			"boolean"
  39		)
  40	end
  41
  42	def change_number_form(
  43		new_tel: nil,
  44		new_backend: nil,
  45		should_delete: false,
  46		from: "test@example.com"
  47	)
  48		iq = Blather::Stanza::Iq::Command.new
  49		iq.form.fields = [
  50			{ var: "new_tel", value: new_tel },
  51			{ var: "should_delete", value: should_delete.to_s },
  52			{ var: "new_backend", value: new_backend }
  53		]
  54		iq.from = from
  55		iq
  56	end
  57
  58	def setup_bandwidth_tn_repo_mock(
  59		should_disconnect: false,
  60		old_tel: nil,
  61		new_tel: nil
  62	)
  63		mock_repo = Minitest::Mock.new
  64		if should_disconnect
  65			expected_order_name = "cust test swap to #{new_tel}"
  66			mock_repo.expect(
  67				:disconnect,
  68				EMPromise.resolve(nil),
  69				[old_tel, expected_order_name]
  70			)
  71		end
  72		mock_repo
  73	end
  74
  75	def assert_ibr_register_form(
  76		iq,
  77		tel,
  78		nick: "test_bw_account",
  79		username: "test_bw_user",
  80		password: "test_bw_password",
  81		from: "customer_test@component",
  82		target_backend_sgx: "sgx"
  83	)
  84		assert iq.is_a?(Blather::Stanza::Iq::IBR)
  85		assert_equal iq.type, :set
  86		assert_equal iq.nick, nick
  87		assert_equal iq.username, username
  88		assert_equal iq.password, password
  89		assert_equal iq.phone, tel
  90		assert_equal iq.from, from
  91		assert_equal iq.to, target_backend_sgx
  92	end
  93
  94	def assert_ibr_deregister_form(
  95		iq,
  96		from: "customer_test@component",
  97		target_backend_sgx: "sgx"
  98	)
  99		assert iq.is_a?(Blather::Stanza::Iq::IBR)
 100		assert_equal iq.type, :set
 101		assert_equal iq.to, target_backend_sgx
 102		assert_equal iq.from, from
 103		assert iq.remove?
 104	end
 105
 106	def admin_command(tel="+15556667777", registered: OpenStruct.new(phone: tel))
 107		sgx = Minitest::Mock.new(OpenStruct.new(
 108			registered?: registered
 109		))
 110		[
 111			sgx,
 112			AdminCommand.new(
 113				customer(sgx: sgx),
 114				CustomerRepo.new(db: FakeDB.new),
 115				AdminActionRepo.new,
 116				Snikket::Repo.new(db: FakeDB.new)
 117			)
 118		]
 119	end
 120
 121	def test_no_user
 122		q_form = Blather::Stanza::Iq::Command.new
 123		q_form.action = :complete
 124		q_form.form.fields = [
 125			{ var: "q", value: "testuser" }
 126		]
 127
 128		customer_repo = Minitest::Mock.new
 129
 130		result = execute_command {
 131			customer_repo.expect(
 132				:find_by_format,
 133				EMPromise.resolve(OpenStruct.new(
 134					customer_id: "testuser",
 135					billing_customer_id: "testuser",
 136					balance: 0.to_d,
 137					jid: Blather::JID.new("test@example.com"),
 138					tndetails: {}
 139				)),
 140				["testuser"]
 141			)
 142
 143			customer_repo.expect(
 144				:find_by_format,
 145				EMPromise.resolve(nil),
 146				[Blather::JID]
 147			)
 148
 149			customer_repo.expect(
 150				:find_by_format,
 151				EMPromise.resolve(nil),
 152				[ProxiedJID]
 153			)
 154
 155			TrivialBackendSgxRepo::REDIS.expect(
 156				:get,
 157				EMPromise.resolve(nil),
 158				["jmp_customer_backend_sgx-testuser"]
 159			)
 160
 161			TrustLevelRepo::REDIS.expect(
 162				:get,
 163				EMPromise.resolve("Customer"),
 164				["jmp_customer_trust_level-testuser"]
 165			)
 166
 167			TrustLevelRepo::REDIS.expect(
 168				:get,
 169				EMPromise.resolve(nil),
 170				["jmp_customer_activater-testuser"]
 171			)
 172
 173			TrustLevelRepo::DB.expect(
 174				:query_one,
 175				EMPromise.resolve({}),
 176				[String, "testuser"], default: {}
 177			)
 178
 179			TrustLevelRepo::DB.expect(
 180				:query_one,
 181				EMPromise.resolve({ settled_amount: 0 }),
 182				[String, "testuser"], default: {}
 183			)
 184
 185			Subaccount::DB.expect(
 186				:query_defer,
 187				EMPromise.resolve([]),
 188				[String, ["testuser"]]
 189			)
 190
 191			Command::COMMAND_MANAGER.expect(
 192				:write,
 193				EMPromise.resolve(q_form),
 194				[Matching.new do |iq|
 195					assert_equal :form, iq.form.type
 196					assert iq.form.field("q")
 197				end]
 198			)
 199
 200			AdminCommand.for(nil, customer_repo).start.catch { |e| e }
 201		}
 202
 203		assert result.stanza.completed?
 204		assert_mock customer_repo
 205		assert_mock Command::COMMAND_MANAGER
 206		assert_mock TrustLevelRepo::REDIS
 207		assert_mock Subaccount::DB
 208		assert_mock TrivialBackendSgxRepo::REDIS
 209	end
 210	em :test_no_user
 211
 212	def test_action_launch_snikket
 213		sgx, admin = admin_command
 214		domain_form = Blather::Stanza::Iq::Command.new
 215		domain_form.form.fields = [
 216			{ var: "domain", value: "test.snikket.chat" }
 217		]
 218
 219		launched = Snikket::Launched.new
 220		launched << Niceogiri::XML::Node.new(
 221			:launched, launched.document, "xmpp:snikket.org/hosting/v1"
 222		).tap { |inner|
 223			inner << Niceogiri::XML::Node.new(
 224				:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
 225			).tap { |id|
 226				id.content = "si-1234"
 227			}
 228			inner << Niceogiri::XML::Node.new(
 229				:bootstrap, launched.document, "xmpp:snikket.org/hosting/v1"
 230			).tap { |bootstrap|
 231				bootstrap << Niceogiri::XML::Node.new(
 232					:token, launched.document, "xmpp:snikket.org/hosting/v1"
 233				).tap { |token|
 234					token.content = "TOKEN"
 235				}
 236			}
 237		}
 238
 239		result = execute_command {
 240			Command::COMMAND_MANAGER.expect(
 241				:write,
 242				EMPromise.resolve(domain_form),
 243				[Matching.new do |iq|
 244					assert_equal :form, iq.form.type
 245					assert iq.form.field("domain")
 246				end]
 247			)
 248			Command::COMMAND_MANAGER.expect(
 249				:write,
 250				EMPromise.reject(:test_result),
 251				[Matching.new do |iq|
 252					assert :result, iq.type
 253					assert(
 254						"https://test.snikket.chat/invites_bootstrap?token=TOKEN",
 255						iq.form.field("bootstrap-uri").value
 256					)
 257				end]
 258			)
 259
 260			AdminAction::LaunchSnikket::IQ_MANAGER.expect(
 261				:write,
 262				EMPromise.resolve(launched),
 263				[Matching.new do |iq|
 264					assert_equal :set, iq.type
 265					assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
 266					assert_equal(
 267						"test.snikket.chat",
 268						iq.xpath(
 269							"./ns:launch/ns:domain",
 270							ns: "xmpp:snikket.org/hosting/v1"
 271						).text
 272					)
 273				end]
 274			)
 275
 276			admin.action_launch_snikket.catch { |e| e }
 277		}
 278
 279		assert_equal :test_result, result
 280		assert_mock sgx
 281		assert_mock AdminAction::LaunchSnikket::IQ_MANAGER
 282		assert_mock Customer::BLATHER
 283	end
 284	em :test_action_launch_snikket
 285
 286	def test_action_cancel_account
 287		req = stub_request(:post, "https://api.churnbuster.io/v1/cancellations")
 288			.with(
 289				body: {
 290					customer: {
 291						source: "braintree",
 292						source_id: "test",
 293						email: "test@smtp.cheogram.com",
 294						properties: {}
 295					},
 296					subscription: {
 297						source: "braintree",
 298						source_id: "test"
 299					}
 300				}.to_json
 301			)
 302			.to_return(status: 200, body: "", headers: {})
 303
 304		sgx, admin = admin_command
 305
 306		Customer::BLATHER.expect(
 307			:<<,
 308			EMPromise.resolve(nil),
 309			[
 310				Matching.new do |m|
 311					assert_equal "Your JMP account has been cancelled.", m.body
 312					assert_equal "test@example.net", m.to.to_s
 313					assert_equal "notify_from@component", m.from.to_s
 314				end
 315			]
 316		)
 317
 318		Customer::BLATHER.expect(
 319			:<<,
 320			EMPromise.resolve(nil),
 321			[
 322				Matching.new do |iq|
 323					assert iq.remove?
 324					assert_equal "test@example.net", iq.to.to_s
 325					assert_equal "component", iq.from.to_s
 326				end
 327			]
 328		)
 329
 330		sgx.expect(:deregister!, EMPromise.resolve(nil))
 331
 332		stub_request(
 333			:post,
 334			"https://dashboard.bandwidth.com/v1.0/accounts//disconnects"
 335		).with(
 336			body: {
 337				name: "test",
 338				DisconnectTelephoneNumberOrderType: {
 339					TelephoneNumberList: {
 340						TelephoneNumber: "5556667777"
 341					}
 342				}
 343			}.to_xml(indent: 0, root: "DisconnectTelephoneNumberOrder")
 344		).to_return(status: 200, body: "")
 345
 346		admin.action_cancel_account.sync
 347
 348		assert_mock sgx
 349		assert_mock BackendSgx::IQ_MANAGER
 350		assert_mock Customer::BLATHER
 351		assert_requested req
 352	end
 353	em :test_action_cancel_account
 354
 355	def test_action_cancel_account_keep_number
 356		details_response = {
 357			TelephoneNumberDetails: {
 358				State: "NY",
 359				City: "MANHATTEN"
 360			}
 361		}.to_xml(indent: 0, root: "TelephoneNumberResponse")
 362
 363		bandwidth_req = stub_request(
 364			:get,
 365			"https://dashboard.bandwidth.com/v1.0/tns/5566667777/tndetails"
 366		).with(
 367			headers: {
 368				"Accept" => "application/xml",
 369				"Accept-Encoding" => "gzip, compressed",
 370				"Authorization" => "Bearer test_bw_oauth_token",
 371				"User-Agent" => "Ruby-Bandwidth-Iris"
 372			}
 373		).to_return(status: 200, body: details_response, headers: {})
 374
 375		churnbuster_req = stub_request(
 376			:post,
 377			"https://api.churnbuster.io/v1/cancellations"
 378		)
 379			.with(
 380				body: {
 381					customer: {
 382						source: "braintree",
 383						source_id: "test",
 384						email: "test@smtp.cheogram.com",
 385						properties: {}
 386					},
 387					subscription: {
 388						source: "braintree",
 389						source_id: "test"
 390					}
 391				}.to_json
 392			)
 393			.to_return(status: 200, body: "", headers: {})
 394
 395		sgx, admin = admin_command("+15566667777")
 396
 397		sql_params = ["+15566667777", "NY", "MANHATTEN", "test_bw_account", 10]
 398
 399		BandwidthTnRepo::DB.expect(
 400			:exec,
 401			EMPromise.resolve(nil),
 402			[String, sql_params]
 403		)
 404
 405		Customer::BLATHER.expect(
 406			:<<,
 407			EMPromise.resolve(nil),
 408			[
 409				Matching.new do |m|
 410					assert_equal "Your JMP account has been cancelled.", m.body
 411					assert_equal "test@example.net", m.to.to_s
 412					assert_equal "notify_from@component", m.from.to_s
 413				end
 414			]
 415		)
 416
 417		Customer::BLATHER.expect(
 418			:<<,
 419			EMPromise.resolve(nil),
 420			[
 421				Matching.new do |iq|
 422					assert iq.remove?
 423					assert_equal "test@example.net", iq.to.to_s
 424					assert_equal "component", iq.from.to_s
 425				end
 426			]
 427		)
 428
 429		sgx.expect(:deregister!, EMPromise.resolve(nil))
 430
 431		admin.action_cancel_account.sync
 432
 433		assert_mock sgx
 434		assert_mock BackendSgx::IQ_MANAGER
 435		assert_mock Customer::BLATHER
 436		assert_mock BandwidthTnRepo::DB
 437
 438		assert_requested churnbuster_req
 439		assert_requested bandwidth_req
 440	end
 441	em :test_action_cancel_account_keep_number
 442
 443	def test_change_num_for_unregistered_customer
 444		bandwidth_tn_repo_mock = setup_bandwidth_tn_repo_mock(
 445			should_disconnect: false
 446		)
 447
 448		BandwidthTnRepo.stub :new, bandwidth_tn_repo_mock do
 449			execute_command { |exe|
 450				sgx = Minitest::Mock.new(OpenStruct.new(
 451					registered?: false,
 452					jid: Blather::JID.new(CONFIG[:sgx]) # Uses Bandwidth backend
 453				))
 454				target_customer = customer(sgx: sgx)
 455
 456				exe.customer_repo.expect(
 457					:find_by_jid,
 458					EMPromise.resolve(target_customer),
 459					[Matching.new do |jid|
 460						assert jid.is_a? Blather::JID
 461						assert_equal jid.stripped.to_s, "test@example.com"
 462					end]
 463				)
 464
 465				AdminAction::NumberChange::REDIS.expect(
 466					:get,
 467					EMPromise.resolve(nil),
 468					["jmp_customer_backend_sgx-test"]
 469				)
 470
 471				AdminAction::NumberChange::REDIS.expect(
 472					:get,
 473					EMPromise.resolve(nil),
 474					["jmp_customer_backend_sgx-test"]
 475				)
 476
 477				AdminAction::NumberChange::REDIS.expect(
 478					:del,
 479					EMPromise.resolve(nil),
 480					["jmp_customer_backend_sgx-#{target_customer.customer_id}"]
 481				)
 482
 483				BackendSgx::IQ_MANAGER.expect(
 484					:write,
 485					EMPromise.resolve(nil)
 486				) do |iq|
 487					assert_ibr_deregister_form(iq)
 488				end
 489
 490				BackendSgx::IQ_MANAGER.expect(
 491					:write,
 492					EMPromise.resolve(nil)
 493				) do |iq|
 494					assert_ibr_register_form(
 495						iq,
 496						"+12222222222"
 497					)
 498				end
 499
 500				BackendSgx::REDIS.expect(
 501					:set,
 502					EMPromise.resolve(nil),
 503					["catapult_jid-+12222222222", "customer_test@component"]
 504				)
 505
 506				expected_xadd_args = {
 507					customer_id: "test",
 508					old_tel: nil,
 509					new_tel: "+12222222222",
 510					should_delete: nil,
 511					actor_id: "test",
 512					class: "NumberChange",
 513					direction: :forward
 514				}.freeze
 515
 516				AdminActionRepo::REDIS.expect(
 517					:xadd,
 518					EMPromise.resolve(nil)
 519				) do |admin_actions, star, **xadd_args|
 520					assert_equal admin_actions, "admin_actions"
 521					assert_equal star, "*"
 522
 523					xadd_args.each do |k, v|
 524						assert_equal v, expected_xadd_args[k]
 525					end
 526				end
 527
 528				Command::COMMAND_MANAGER.expect(
 529					:write,
 530					EMPromise.resolve(change_number_form(
 531						new_tel: "+12222222222"
 532					))
 533				) do |iq|
 534					assert_undoable_form(iq)
 535					assert_change_number_form(iq)
 536				end
 537
 538				result = AdminCommand.for(
 539					target_customer,
 540					exe.customer_repo
 541				).action_number_change.sync
 542
 543				slug, backend_report, number_report = result.lines
 544
 545				assert_equal slug.strip, "Action : Change Number"
 546				assert_equal(
 547					backend_report.strip,
 548					"[move backend?]: sgx -> sgx"
 549				)
 550				assert_equal(
 551					number_report.strip,
 552					"[change number?]: nil -> +12222222222"
 553				)
 554
 555				assert_mock Command::COMMAND_MANAGER
 556				assert_mock exe.customer_repo
 557				assert_mock AdminAction::NumberChange::REDIS
 558				assert_mock AdminActionRepo::REDIS
 559				assert_mock BackendSgx::REDIS
 560				assert_mock BackendSgx::IQ_MANAGER
 561				assert_mock bandwidth_tn_repo_mock
 562				assert_mock sgx
 563			}
 564		end
 565	end
 566	em :test_change_num_for_unregistered_customer
 567
 568	def test_change_num_for_unregistered_customer_blank_new_tel
 569		bandwidth_tn_repo_mock = setup_bandwidth_tn_repo_mock(
 570			should_disconnect: false
 571		)
 572
 573		BandwidthTnRepo.stub :new, bandwidth_tn_repo_mock do
 574			execute_command { |exe|
 575				sgx = Minitest::Mock.new(OpenStruct.new(
 576					registered?: false,
 577					jid: Blather::JID.new(CONFIG[:sgx]) # Uses Bandwidth backend
 578				))
 579				target_customer = customer(sgx: sgx)
 580
 581				exe.customer_repo.expect(
 582					:find_by_jid,
 583					EMPromise.resolve(target_customer),
 584					[Matching.new do |jid|
 585						assert jid.is_a? Blather::JID
 586						assert_equal jid.stripped.to_s, "test@example.com"
 587					end]
 588				)
 589
 590				Command::COMMAND_MANAGER.expect(
 591					:write,
 592					EMPromise.resolve(change_number_form(
 593						new_tel: ""
 594					))
 595				) do |iq|
 596					assert_undoable_form(iq)
 597					assert_change_number_form(iq)
 598				end
 599
 600				result = assert_raises {
 601					AdminCommand.for(
 602						target_customer,
 603						exe.customer_repo
 604					).action_number_change.sync
 605				}
 606
 607				assert_kind_of AdminAction::NumberChange::Orphan, result
 608
 609				assert_mock Command::COMMAND_MANAGER
 610				assert_mock exe.customer_repo
 611				assert_mock bandwidth_tn_repo_mock
 612				assert_mock sgx
 613			}
 614		end
 615	end
 616	em :test_change_num_for_unregistered_customer_blank_new_tel
 617
 618	def test_change_num_same_num_same_backend
 619		# Same as default given by `sgx.registered?` returned by `admin_command`
 620		tel = "+15556667777"
 621
 622		execute_command { |exe|
 623			sgx = Minitest::Mock.new(OpenStruct.new(
 624				registered?: OpenStruct.new(phone: tel),
 625				jid: Blather::JID.new(CONFIG[:sgx]) # Uses Bandwidth backend
 626			))
 627
 628			target_customer = customer(sgx: sgx)
 629			admin = AdminCommand.for(target_customer, exe.customer_repo)
 630
 631			exe.customer_repo.expect(
 632				:find_by_jid,
 633				EMPromise.resolve(target_customer),
 634				[Matching.new do |jid|
 635					assert jid.is_a? Blather::JID
 636					assert_equal jid.stripped.to_s, "test@example.com"
 637				end]
 638			)
 639
 640			Command::COMMAND_MANAGER.expect(
 641				:write,
 642				EMPromise.resolve(change_number_form(
 643					new_tel: tel,
 644					new_backend: "sgx"
 645				)),
 646				[Matching.new do |iq|
 647					assert_undoable_form(iq)
 648					assert_change_number_form(iq)
 649				end]
 650			)
 651
 652			error = admin.action_number_change
 653				.catch_only(AdminAction::NoOp) { |e| e }.sync
 654
 655			assert error.is_a?(AdminAction::NoOp)
 656			assert_mock Command::COMMAND_MANAGER
 657			assert_mock exe.customer_repo
 658			assert_mock AdminAction::NumberChange::REDIS
 659			assert_mock sgx
 660		}
 661	end
 662	em :test_change_num_same_num_same_backend
 663
 664	def test_change_num_blank_num_blank_backend
 665		# Same as default given by `sgx.registered?` returned by `admin_command`
 666		tel = "+15556667777"
 667
 668		execute_command { |exe|
 669			sgx = Minitest::Mock.new(OpenStruct.new(
 670				registered?: OpenStruct.new(phone: tel),
 671				jid: Blather::JID.new(CONFIG[:sgx]) # Uses Bandwidth backend
 672			))
 673
 674			target_customer = customer(sgx: sgx)
 675
 676			admin = AdminCommand.for(target_customer, exe.customer_repo)
 677
 678			exe.customer_repo.expect(
 679				:find_by_jid,
 680				EMPromise.resolve(target_customer),
 681				[Matching.new do |jid|
 682					assert jid.is_a? Blather::JID
 683					assert_equal jid.stripped.to_s, "test@example.com"
 684				end]
 685			)
 686
 687			Command::COMMAND_MANAGER.expect(
 688				:write,
 689				EMPromise.resolve(change_number_form),
 690				[Matching.new do |iq|
 691					assert_undoable_form(iq)
 692					assert_change_number_form(iq)
 693				end]
 694			)
 695
 696			error = admin.action_number_change
 697				.catch_only(AdminAction::NoOp) { |e| e }.sync
 698
 699			assert error.is_a?(AdminAction::NoOp)
 700			assert_mock Command::COMMAND_MANAGER
 701			assert_mock exe.customer_repo
 702			assert_mock AdminAction::NumberChange::REDIS
 703			assert_mock sgx
 704		}
 705	end
 706	em :test_change_num_blank_num_blank_backend
 707
 708	def test_change_num_different_num_same_backend
 709		old_tel = "+15556667777"
 710		new_tel = "+12222222222"
 711		bandwidth_tn_repo_mock = setup_bandwidth_tn_repo_mock(
 712			should_disconnect: false
 713		)
 714
 715		BandwidthTnRepo.stub :new, bandwidth_tn_repo_mock do
 716			execute_command { |exe|
 717				sgx = Minitest::Mock.new(OpenStruct.new(
 718					registered?: OpenStruct.new(phone: old_tel),
 719					jid: Blather::JID.new(CONFIG[:sgx])
 720				))
 721
 722				target_customer = customer(sgx: sgx)
 723				admin = AdminCommand.for(target_customer, exe.customer_repo)
 724
 725				exe.customer_repo.expect(
 726					:find_by_jid,
 727					EMPromise.resolve(target_customer),
 728					[Matching.new do |jid|
 729						assert jid.is_a? Blather::JID
 730						assert_equal jid.stripped.to_s, "test@example.com"
 731					end]
 732				)
 733
 734				AdminAction::NumberChange::REDIS.expect(
 735					:rename,
 736					EMPromise.resolve(nil),
 737					["catapult_fwd-#{old_tel}", "catapult_fwd-#{new_tel}"]
 738				)
 739
 740				AdminAction::NumberChange::REDIS.expect(
 741					:get,
 742					EMPromise.resolve(nil),
 743					["jmp_customer_backend_sgx-test"]
 744				)
 745				AdminAction::NumberChange::REDIS.expect(
 746					:get,
 747					EMPromise.resolve(nil),
 748					["jmp_customer_backend_sgx-test"]
 749				)
 750
 751				BackendSgx::IQ_MANAGER.expect(
 752					:write,
 753					EMPromise.resolve(nil)
 754				) do |iq|
 755					assert_ibr_deregister_form(iq)
 756				end
 757
 758				BackendSgx::IQ_MANAGER.expect(
 759					:write,
 760					EMPromise.resolve(nil)
 761				) do |iq|
 762					assert_ibr_register_form(
 763						iq,
 764						"+12222222222"
 765					)
 766				end
 767
 768				AdminAction::NumberChange::REDIS.expect(
 769					:del,
 770					EMPromise.resolve(nil),
 771					["jmp_customer_backend_sgx-#{target_customer.customer_id}"]
 772				)
 773
 774				BackendSgx::REDIS.expect(
 775					:set,
 776					EMPromise.resolve(nil),
 777					["catapult_jid-#{new_tel}", "customer_test@component"]
 778				)
 779
 780				Command::COMMAND_MANAGER.expect(
 781					:write,
 782					EMPromise.resolve(change_number_form(
 783						new_tel: "+12222222222"
 784					))
 785				) do |iq|
 786					assert_undoable_form(iq)
 787					assert_change_number_form(iq)
 788				end
 789
 790				expected_xadd_args = {
 791					customer_id: "test",
 792					old_tel: old_tel,
 793					new_tel: new_tel,
 794					should_delete: nil,
 795					actor_id: "test",
 796					class: "NumberChange",
 797					direction: :forward
 798				}.freeze
 799
 800				AdminActionRepo::REDIS.expect(
 801					:xadd,
 802					EMPromise.resolve(nil)
 803				) do |admin_actions, star, **xadd_args|
 804					assert_equal admin_actions, "admin_actions"
 805					assert_equal star, "*"
 806
 807					xadd_args.each do |k, v|
 808						assert_equal v, expected_xadd_args[k]
 809					end
 810				end
 811
 812				result = admin.action_number_change.sync
 813
 814				slug, backend_report, number_report = result.lines
 815
 816				assert_equal slug.strip, "Action : Change Number"
 817				assert_equal(
 818					backend_report.strip,
 819					"[move backend?]: sgx -> sgx"
 820				)
 821				assert_equal(
 822					number_report.strip,
 823					"[change number?]: +15556667777 -> +12222222222"
 824				)
 825
 826				assert_mock Command::COMMAND_MANAGER
 827				assert_mock exe.customer_repo
 828				assert_mock AdminAction::NumberChange::REDIS
 829				assert_mock AdminActionRepo::REDIS
 830				assert_mock BackendSgx::REDIS
 831				assert_mock BackendSgx::IQ_MANAGER
 832				assert_mock bandwidth_tn_repo_mock
 833				assert_mock sgx
 834			}
 835		end
 836	end
 837	em :test_change_num_different_num_same_backend
 838
 839	def test_change_num_same_num_different_backend
 840		target_backend_sgx = "route_value"
 841
 842		bandwidth_tn_repo_mock = setup_bandwidth_tn_repo_mock(
 843			should_disconnect: false
 844		)
 845
 846		BandwidthTnRepo.stub :new, bandwidth_tn_repo_mock do
 847			execute_command { |exe|
 848				sgx = Minitest::Mock.new(OpenStruct.new(
 849					registered?: OpenStruct.new(phone: "+15556667777"),
 850					jid: Blather::JID.new(CONFIG[:sgx])
 851				))
 852
 853				target_customer = customer(sgx: sgx)
 854				admin = AdminCommand.for(target_customer, exe.customer_repo)
 855
 856				exe.customer_repo.expect(
 857					:find_by_jid,
 858					EMPromise.resolve(target_customer),
 859					[Matching.new do |jid|
 860						assert jid.is_a? Blather::JID
 861						assert_equal jid.stripped.to_s, "test@example.com"
 862					end]
 863				)
 864
 865				Command::COMMAND_MANAGER.expect(
 866					:write,
 867					EMPromise.resolve(
 868						change_number_form(
 869							new_backend: target_backend_sgx
 870						)
 871					),
 872					[Matching.new do |iq|
 873						assert_undoable_form(iq)
 874						assert_change_number_form(iq)
 875					end]
 876				)
 877
 878				BackendSgx::IQ_MANAGER.expect(
 879					:write,
 880					EMPromise.resolve(nil)
 881				) do |iq|
 882					assert_ibr_deregister_form(iq)
 883				end
 884
 885				BackendSgx::IQ_MANAGER.expect(
 886					:write,
 887					EMPromise.resolve(nil)
 888				) do |iq|
 889					assert_ibr_register_form(
 890						iq,
 891						"+15556667777",
 892						target_backend_sgx: target_backend_sgx,
 893						nick: "test_sgx_account",
 894						username: "test_sgx_user",
 895						password: "test_sgx_password"
 896					)
 897				end
 898
 899				AdminAction::NumberChange::REDIS.expect(
 900					:get,
 901					EMPromise.resolve(nil),
 902					["jmp_customer_backend_sgx-#{target_customer.customer_id}"]
 903				)
 904
 905				AdminAction::NumberChange::REDIS.expect(
 906					:set,
 907					EMPromise.resolve(nil),
 908					[
 909						"jmp_customer_backend_sgx-#{target_customer.customer_id}",
 910						"route_value"
 911					]
 912				)
 913
 914				AdminAction::NumberChange::REDIS.expect(
 915					:get,
 916					EMPromise.resolve("route_value"),
 917					["jmp_customer_backend_sgx-#{target_customer.customer_id}"]
 918				)
 919
 920				BackendSgx::REDIS.expect(
 921					:set,
 922					EMPromise.resolve(nil),
 923					[
 924						"catapult_jid-+15556667777",
 925						"customer_test@component"
 926					]
 927				)
 928
 929				expected_xadd_args = {
 930					old_tel: "+15556667777",
 931					new_tel: "+15556667777",
 932					old_backend: "sgx",
 933					new_backend: "route_value",
 934					should_delete: nil,
 935					actor_id: "test",
 936					class: "NumberChange",
 937					direction: :forward
 938				}.freeze
 939
 940				AdminActionRepo::REDIS.expect(
 941					:xadd,
 942					EMPromise.resolve(nil)
 943				) do |admin_actions, star, **xadd_args|
 944					assert_equal admin_actions, "admin_actions"
 945					assert_equal star, "*"
 946
 947					xadd_args.each do |k, v|
 948						assert_equal v, expected_xadd_args[k]
 949					end
 950				end
 951
 952				result = admin.action_number_change.sync
 953
 954				slug, backend_report, number_report = result.lines
 955
 956				assert_equal slug.strip, "Action : Change Number"
 957				assert_equal(
 958					backend_report.strip,
 959					"[move backend?]: sgx -> route_value"
 960				)
 961				assert_equal(
 962					number_report.strip,
 963					"[change number?]: +15556667777 -> +15556667777"
 964				)
 965
 966				assert_mock Command::COMMAND_MANAGER
 967				assert_mock exe.customer_repo
 968				assert_mock AdminAction::NumberChange::REDIS
 969				assert_mock AdminActionRepo::REDIS
 970				assert_mock BackendSgx::REDIS
 971				assert_mock BackendSgx::IQ_MANAGER
 972				assert_mock bandwidth_tn_repo_mock
 973				assert_mock sgx
 974			}
 975		end
 976	end
 977	em :test_change_num_same_num_different_backend
 978
 979	def test_change_num_different_num_different_backend
 980		old_tel = "+15556667777"
 981		new_tel = "+12222222222"
 982		target_backend_sgx = "route_value"
 983
 984		bandwidth_tn_repo_mock = setup_bandwidth_tn_repo_mock(
 985			should_disconnect: false
 986		)
 987
 988		BandwidthTnRepo.stub :new, bandwidth_tn_repo_mock do
 989			execute_command { |exe|
 990				sgx = Minitest::Mock.new(OpenStruct.new(
 991					registered?: OpenStruct.new(phone: old_tel),
 992					jid: Blather::JID.new(CONFIG[:sgx])
 993				))
 994
 995				target_customer = customer(sgx: sgx)
 996				admin = AdminCommand.for(target_customer, exe.customer_repo)
 997
 998				exe.customer_repo.expect(
 999					:find_by_jid,
1000					EMPromise.resolve(target_customer),
1001					[Matching.new do |jid|
1002						assert jid.is_a? Blather::JID
1003						assert_equal jid.stripped.to_s, "test@example.com"
1004					end]
1005				)
1006
1007				Command::COMMAND_MANAGER.expect(
1008					:write,
1009					EMPromise.resolve(
1010						change_number_form(
1011							new_tel: new_tel,
1012							new_backend: target_backend_sgx
1013						)
1014					),
1015					[Matching.new do |iq|
1016						assert_undoable_form(iq)
1017						assert_change_number_form(iq)
1018					end]
1019				)
1020
1021				BackendSgx::IQ_MANAGER.expect(
1022					:write,
1023					EMPromise.resolve(nil)
1024				) do |iq|
1025					assert_ibr_deregister_form(iq)
1026				end
1027
1028				BackendSgx::IQ_MANAGER.expect(
1029					:write,
1030					EMPromise.resolve(nil)
1031				) do |iq|
1032					assert_ibr_register_form(
1033						iq,
1034						"+12222222222",
1035						target_backend_sgx: target_backend_sgx,
1036						nick: "test_sgx_account",
1037						username: "test_sgx_user",
1038						password: "test_sgx_password"
1039					)
1040				end
1041
1042				AdminAction::NumberChange::REDIS.expect(
1043					:rename,
1044					EMPromise.resolve(nil),
1045					["catapult_fwd-#{old_tel}", "catapult_fwd-#{new_tel}"]
1046				)
1047
1048				AdminAction::NumberChange::REDIS.expect(
1049					:get,
1050					EMPromise.resolve(nil),
1051					["jmp_customer_backend_sgx-test"]
1052				)
1053
1054				AdminAction::NumberChange::REDIS.expect(
1055					:set,
1056					EMPromise.resolve(nil),
1057					[
1058						"jmp_customer_backend_sgx-#{target_customer.customer_id}",
1059						"route_value"
1060					]
1061				)
1062
1063				AdminAction::NumberChange::REDIS.expect(
1064					:get,
1065					EMPromise.resolve("route_value"),
1066					["jmp_customer_backend_sgx-test"]
1067				)
1068
1069				BackendSgx::REDIS.expect(
1070					:set,
1071					EMPromise.resolve(nil),
1072					[
1073						"catapult_jid-#{new_tel}",
1074						"customer_test@component"
1075					]
1076				)
1077
1078				expected_xadd_args = {
1079					old_tel: "+15556667777",
1080					new_tel: "+12222222222",
1081					target_backend_sgx: "route_value",
1082					should_delete: nil,
1083					actor_id: "test",
1084					class: "NumberChange",
1085					direction: :forward
1086				}.freeze
1087
1088				AdminActionRepo::REDIS.expect(
1089					:xadd,
1090					EMPromise.resolve(nil)
1091				) do |admin_actions, star, **xadd_args|
1092					assert_equal admin_actions, "admin_actions"
1093					assert_equal star, "*"
1094
1095					xadd_args.each do |k, v|
1096						assert_equal v, expected_xadd_args[k]
1097					end
1098				end
1099
1100				result = admin.action_number_change.sync
1101
1102				slug, backend_report, number_report = result.lines
1103
1104				assert_equal slug.strip, "Action : Change Number"
1105				assert_equal(
1106					backend_report.strip,
1107					"[move backend?]: sgx -> route_value"
1108				)
1109				assert_equal(
1110					number_report.strip,
1111					"[change number?]: +15556667777 -> +12222222222"
1112				)
1113
1114				assert_mock Command::COMMAND_MANAGER
1115				assert_mock exe.customer_repo
1116				assert_mock AdminAction::NumberChange::REDIS
1117				assert_mock AdminActionRepo::REDIS
1118				assert_mock BackendSgx::REDIS
1119				assert_mock BackendSgx::IQ_MANAGER
1120				assert_mock bandwidth_tn_repo_mock
1121				assert_mock sgx
1122			}
1123		end
1124	end
1125	em :test_change_num_different_num_different_backend
1126
1127	def test_change_num_bandwidth_backend_with_delete_should_disconnect
1128		old_tel = "+15556667777"
1129		new_tel = "+12222222222"
1130
1131		bandwidth_tn_repo_mock = setup_bandwidth_tn_repo_mock(
1132			should_disconnect: true,
1133			old_tel: old_tel,
1134			new_tel: new_tel
1135		)
1136
1137		BandwidthTnRepo.stub :new, bandwidth_tn_repo_mock do
1138			execute_command { |exe|
1139				sgx = Minitest::Mock.new(OpenStruct.new(
1140					registered?: OpenStruct.new(phone: old_tel),
1141					jid: Blather::JID.new(CONFIG[:sgx])
1142				))
1143
1144				target_customer = customer(sgx: sgx)
1145				admin = AdminCommand.for(target_customer, exe.customer_repo)
1146
1147				exe.customer_repo.expect(
1148					:find_by_jid,
1149					EMPromise.resolve(customer(sgx: sgx)),
1150					[Matching.new do |jid|
1151						assert jid.is_a? Blather::JID
1152						assert_equal jid.stripped.to_s, "test@example.com"
1153					end]
1154				)
1155
1156				AdminAction::NumberChange::REDIS.expect(
1157					:rename,
1158					EMPromise.resolve(nil),
1159					["catapult_fwd-#{old_tel}", "catapult_fwd-#{new_tel}"]
1160				)
1161
1162				expected_xadd_args = {
1163					customer_id: "test",
1164					old_tel: old_tel,
1165					new_tel: new_tel,
1166					should_delete: "true",
1167					actor_id: "test",
1168					class: "NumberChange",
1169					direction: :forward
1170				}.freeze
1171
1172				AdminActionRepo::REDIS.expect(
1173					:xadd,
1174					EMPromise.resolve(nil)
1175				) do |admin_actions, star, **xadd_args|
1176					assert_equal admin_actions, "admin_actions"
1177					assert_equal star, "*"
1178
1179					xadd_args.each do |k, v|
1180						assert_equal v, expected_xadd_args[k]
1181					end
1182				end
1183
1184				Command::COMMAND_MANAGER.expect(
1185					:write,
1186					EMPromise.resolve(
1187						change_number_form(
1188							new_tel: new_tel,
1189							should_delete: true
1190						)
1191					),
1192					[Matching.new do |iq|
1193						assert_undoable_form(iq)
1194						assert_change_number_form(iq)
1195					end]
1196				)
1197
1198				AdminAction::NumberChange::REDIS.expect(
1199					:get,
1200					EMPromise.resolve(nil),
1201					["jmp_customer_backend_sgx-test"]
1202				)
1203
1204				AdminAction::NumberChange::REDIS.expect(
1205					:del,
1206					EMPromise.resolve(nil),
1207					["jmp_customer_backend_sgx-test"]
1208				)
1209
1210				AdminAction::NumberChange::REDIS.expect(
1211					:get,
1212					EMPromise.resolve(nil),
1213					["jmp_customer_backend_sgx-test"]
1214				)
1215
1216				BackendSgx::REDIS.expect(
1217					:set,
1218					EMPromise.resolve(nil),
1219					[
1220						"catapult_jid-#{new_tel}",
1221						"customer_test@component"
1222					]
1223				)
1224
1225				BackendSgx::IQ_MANAGER.expect(
1226					:write,
1227					EMPromise.resolve(nil)
1228				) do |iq|
1229					assert_ibr_deregister_form(iq)
1230				end
1231
1232				BackendSgx::IQ_MANAGER.expect(
1233					:write,
1234					EMPromise.resolve(nil)
1235				) do |iq|
1236					assert_ibr_register_form(
1237						iq,
1238						new_tel,
1239						nick: "test_bw_account",
1240						username: "test_bw_user",
1241						password: "test_bw_password"
1242					)
1243				end
1244
1245				result = admin.action_number_change.sync
1246
1247				slug, backend_report, number_report = result.lines
1248
1249				assert_equal slug.strip, "Action : Change Number"
1250				assert_equal(
1251					backend_report.strip,
1252					"[move backend?]: sgx -> sgx"
1253				)
1254				assert_equal(
1255					number_report.strip,
1256					"[change number?]: #{old_tel} -> #{new_tel}"
1257				)
1258
1259				assert_mock Command::COMMAND_MANAGER
1260				assert_mock exe.customer_repo
1261				assert_mock AdminAction::NumberChange::REDIS
1262				assert_mock AdminActionRepo::REDIS
1263				assert_mock BackendSgx::REDIS
1264				assert_mock BackendSgx::IQ_MANAGER
1265				assert_mock bandwidth_tn_repo_mock
1266				assert_mock sgx
1267			}
1268		end
1269	end
1270	em :test_change_num_bandwidth_backend_with_delete_should_disconnect
1271
1272	def test_change_num_non_bw_backend_should_not_disconnect
1273		old_tel = "+15556667777"
1274		new_tel = "+12222222222"
1275		non_bw_backend = "route_value"
1276
1277		bandwidth_tn_repo_mock = setup_bandwidth_tn_repo_mock(
1278			should_disconnect: false
1279		)
1280
1281		BandwidthTnRepo.stub :new, bandwidth_tn_repo_mock do
1282			execute_command { |exe|
1283				Command::COMMAND_MANAGER.expect(
1284					:write,
1285					EMPromise.resolve(change_number_form(new_tel: new_tel)),
1286					[Matching.new do |iq|
1287						assert_undoable_form(iq)
1288						assert_change_number_form(iq)
1289					end]
1290				)
1291
1292				non_bandwidth_sgx = Minitest::Mock.new(OpenStruct.new(
1293					registered?: OpenStruct.new(phone: old_tel),
1294					jid: Blather::JID.new(non_bw_backend)
1295				))
1296
1297				target_customer = customer(sgx: non_bandwidth_sgx)
1298				admin = AdminCommand.for(target_customer, exe.customer_repo)
1299
1300				exe.customer_repo.expect(
1301					:find_by_jid,
1302					EMPromise.resolve(target_customer),
1303					[Blather::JID.new("test@example.com")]
1304				)
1305
1306				AdminAction::NumberChange::REDIS.expect(
1307					:rename,
1308					EMPromise.resolve(nil),
1309					["catapult_fwd-#{old_tel}", "catapult_fwd-#{new_tel}"]
1310				)
1311
1312				AdminAction::NumberChange::REDIS.expect(
1313					:get,
1314					EMPromise.resolve("route_value"),
1315					["jmp_customer_backend_sgx-#{target_customer.customer_id}"]
1316				)
1317
1318				BackendSgx::IQ_MANAGER.expect(
1319					:write,
1320					EMPromise.resolve(nil)
1321				) do |iq|
1322					assert_ibr_deregister_form(
1323						iq,
1324						target_backend_sgx: "route_value"
1325					)
1326				end
1327
1328				AdminAction::NumberChange::REDIS.expect(
1329					:set,
1330					EMPromise.resolve(nil),
1331					[
1332						"jmp_customer_backend_sgx-#{target_customer.customer_id}",
1333						"route_value"
1334					]
1335				)
1336
1337				AdminAction::NumberChange::REDIS.expect(
1338					:get,
1339					EMPromise.resolve("route_value"),
1340					["jmp_customer_backend_sgx-#{target_customer.customer_id}"]
1341				)
1342
1343				BackendSgx::IQ_MANAGER.expect(
1344					:write,
1345					EMPromise.resolve(nil)
1346				) do |iq|
1347					assert_ibr_register_form(
1348						iq,
1349						"+12222222222",
1350						nick: "test_sgx_account",
1351						username: "test_sgx_user",
1352						password: "test_sgx_password",
1353						target_backend_sgx: "route_value"
1354					)
1355				end
1356
1357				BackendSgx::REDIS.expect(
1358					:set,
1359					EMPromise.resolve(nil),
1360					["catapult_jid-+12222222222", "customer_test@component"]
1361				)
1362
1363				expected_xadd_args = {
1364					customer_id: "test",
1365					old_tel: old_tel,
1366					new_tel: new_tel,
1367					should_delete: "true",
1368					actor_id: "test",
1369					class: "NumberChange",
1370					direction: :forward
1371				}.freeze
1372
1373				AdminActionRepo::REDIS.expect(
1374					:xadd,
1375					EMPromise.resolve(nil)
1376				) do |admin_actions, star, **xadd_args|
1377					assert_equal admin_actions, "admin_actions"
1378					assert_equal star, "*"
1379
1380					xadd_args.each do |k, v|
1381						assert_equal v, expected_xadd_args[k]
1382					end
1383				end
1384
1385				result = admin.action_number_change.sync
1386
1387				slug, backend_report, number_report = result.lines
1388
1389				assert_equal slug.strip, "Action : Change Number"
1390				assert_equal(
1391					backend_report.strip,
1392					"[move backend?]: #{non_bw_backend} -> #{non_bw_backend}"
1393				)
1394				assert_equal(
1395					number_report.strip,
1396					"[change number?]: +15556667777 -> +12222222222"
1397				)
1398
1399				assert_mock Command::COMMAND_MANAGER
1400				assert_mock exe.customer_repo
1401				assert_mock AdminAction::NumberChange::REDIS
1402				assert_mock AdminActionRepo::REDIS
1403				assert_mock BackendSgx::REDIS
1404				assert_mock BackendSgx::IQ_MANAGER
1405				assert_mock bandwidth_tn_repo_mock
1406				assert_mock non_bandwidth_sgx
1407			}
1408		end
1409	end
1410	em :test_change_num_non_bw_backend_should_not_disconnect
1411end