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