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		execute_command { |exe|
 436			sgx = Minitest::Mock.new(OpenStruct.new(
 437				registered?: nil,
 438				jid: Blather::JID.new(CONFIG[:sgx]) # Uses Bandwidth backend
 439			))
 440			target_customer = customer(sgx: sgx)
 441			admin = AdminCommand.for(target_customer, exe.customer_repo)
 442
 443			error = assert_raises(
 444				"number change for unregistered customer should raise"
 445			) {
 446				admin.action_number_change.sync
 447			}
 448
 449			assert_equal error.to_s, "Customer not registered"
 450		}
 451	end
 452	em :test_change_num_for_unregistered_customer
 453
 454	def test_change_num_same_num_same_backend
 455		# Same as default given by `sgx.registered?` returned by `admin_command`
 456		tel = "+15556667777"
 457
 458		execute_command { |exe|
 459			sgx = Minitest::Mock.new(OpenStruct.new(
 460				registered?: OpenStruct.new(phone: tel),
 461				jid: Blather::JID.new(CONFIG[:sgx]) # Uses Bandwidth backend
 462			))
 463
 464			target_customer = customer(sgx: sgx)
 465			admin = AdminCommand.for(target_customer, exe.customer_repo)
 466
 467			exe.customer_repo.expect(
 468				:find_by_jid,
 469				EMPromise.resolve(target_customer),
 470				[Matching.new do |jid|
 471					assert jid.is_a? Blather::JID
 472					assert_equal jid.stripped.to_s, "test@example.com"
 473				end]
 474			)
 475
 476			AdminAction::NumberChange::REDIS.expect(
 477				:exists,
 478				EMPromise.resolve(1),
 479				["catapult_jid-#{tel}"]
 480			)
 481
 482			Command::COMMAND_MANAGER.expect(
 483				:write,
 484				EMPromise.resolve(change_number_form(
 485					new_tel: tel,
 486					new_backend: "sgx"
 487				)),
 488				[Matching.new do |iq|
 489					assert_undoable_form(iq)
 490					assert_change_number_form(iq)
 491				end]
 492			)
 493
 494			error = admin.action_number_change
 495				.catch_only(AdminAction::NoOp) { |e| e }.sync
 496
 497			assert error.is_a?(AdminAction::NoOp)
 498			assert_mock Command::COMMAND_MANAGER
 499			assert_mock exe.customer_repo
 500			assert_mock AdminAction::NumberChange::REDIS
 501			assert_mock sgx
 502		}
 503	end
 504	em :test_change_num_same_num_same_backend
 505
 506	def test_change_num_blank_num_blank_backend
 507		# Same as default given by `sgx.registered?` returned by `admin_command`
 508		tel = "+15556667777"
 509
 510		execute_command { |exe|
 511			sgx = Minitest::Mock.new(OpenStruct.new(
 512				registered?: OpenStruct.new(phone: tel),
 513				jid: Blather::JID.new(CONFIG[:sgx]) # Uses Bandwidth backend
 514			))
 515
 516			target_customer = customer(sgx: sgx)
 517
 518			admin = AdminCommand.for(target_customer, exe.customer_repo)
 519
 520			exe.customer_repo.expect(
 521				:find_by_jid,
 522				EMPromise.resolve(target_customer),
 523				[Matching.new do |jid|
 524					assert jid.is_a? Blather::JID
 525					assert_equal jid.stripped.to_s, "test@example.com"
 526				end]
 527			)
 528
 529			AdminAction::NumberChange::REDIS.expect(
 530				:exists,
 531				EMPromise.resolve(1),
 532				["catapult_jid-#{tel}"]
 533			)
 534
 535			Command::COMMAND_MANAGER.expect(
 536				:write,
 537				EMPromise.resolve(change_number_form),
 538				[Matching.new do |iq|
 539					assert_undoable_form(iq)
 540					assert_change_number_form(iq)
 541				end]
 542			)
 543
 544			error = admin.action_number_change
 545				.catch_only(AdminAction::NoOp) { |e| e }.sync
 546
 547			assert error.is_a?(AdminAction::NoOp)
 548			assert_mock Command::COMMAND_MANAGER
 549			assert_mock exe.customer_repo
 550			assert_mock AdminAction::NumberChange::REDIS
 551			assert_mock sgx
 552		}
 553	end
 554	em :test_change_num_blank_num_blank_backend
 555
 556	def test_change_num_different_num_same_backend
 557		old_tel = "+15556667777"
 558		new_tel = "+12222222222"
 559		bandwidth_tn_repo_mock = setup_bandwidth_tn_repo_mock(
 560			should_disconnect: false
 561		)
 562
 563		BandwidthTnRepo.stub :new, bandwidth_tn_repo_mock do
 564			execute_command { |exe|
 565				sgx = Minitest::Mock.new(OpenStruct.new(
 566					registered?: OpenStruct.new(phone: old_tel),
 567					jid: Blather::JID.new(CONFIG[:sgx])
 568				))
 569
 570				target_customer = customer(sgx: sgx)
 571				admin = AdminCommand.for(target_customer, exe.customer_repo)
 572
 573				exe.customer_repo.expect(
 574					:find_by_jid,
 575					EMPromise.resolve(target_customer),
 576					[Matching.new do |jid|
 577						assert jid.is_a? Blather::JID
 578						assert_equal jid.stripped.to_s, "test@example.com"
 579					end]
 580				)
 581
 582				AdminAction::NumberChange::REDIS.expect(
 583					:rename,
 584					EMPromise.resolve(nil),
 585					["catapult_fwd-#{old_tel}", "catapult_fwd-#{new_tel}"]
 586				)
 587
 588				AdminAction::NumberChange::REDIS.expect(
 589					:get,
 590					EMPromise.resolve(nil),
 591					["jmp_customer_backend_sgx-test"]
 592				)
 593				AdminAction::NumberChange::REDIS.expect(
 594					:get,
 595					EMPromise.resolve(nil),
 596					["jmp_customer_backend_sgx-test"]
 597				)
 598
 599				BackendSgx::IQ_MANAGER.expect(
 600					:write,
 601					EMPromise.resolve(nil)
 602				) do |iq|
 603					assert_ibr_deregister_form(iq)
 604				end
 605
 606				BackendSgx::IQ_MANAGER.expect(
 607					:write,
 608					EMPromise.resolve(nil)
 609				) do |iq|
 610					assert_ibr_register_form(
 611						iq,
 612						"+12222222222"
 613					)
 614				end
 615
 616				AdminAction::NumberChange::REDIS.expect(
 617					:del,
 618					EMPromise.resolve(nil),
 619					["jmp_customer_backend_sgx-#{target_customer.customer_id}"]
 620				)
 621
 622				BackendSgx::REDIS.expect(
 623					:set,
 624					EMPromise.resolve(nil),
 625					["catapult_jid-#{new_tel}", "customer_test@component"]
 626				)
 627
 628				AdminAction::NumberChange::REDIS.expect(
 629					:exists,
 630					EMPromise.resolve(1),
 631					["catapult_jid-#{old_tel}"]
 632				)
 633
 634				Command::COMMAND_MANAGER.expect(
 635					:write,
 636					EMPromise.resolve(change_number_form(
 637						new_tel: "+12222222222"
 638					))
 639				) do |iq|
 640					assert_undoable_form(iq)
 641					assert_change_number_form(iq)
 642				end
 643
 644				expected_xadd_args = {
 645					customer_id: "test",
 646					old_tel: old_tel,
 647					new_tel: new_tel,
 648					should_delete: nil,
 649					actor_id: "test",
 650					class: "NumberChange",
 651					direction: :forward
 652				}.freeze
 653
 654				AdminActionRepo::REDIS.expect(
 655					:xadd,
 656					EMPromise.resolve(nil)
 657				) do |admin_actions, star, **xadd_args|
 658					assert_equal admin_actions, "admin_actions"
 659					assert_equal star, "*"
 660
 661					xadd_args.each do |k, v|
 662						assert_equal v, expected_xadd_args[k]
 663					end
 664				end
 665
 666				result = admin.action_number_change.sync
 667
 668				slug, backend_report, number_report = result.lines
 669
 670				assert_equal slug.strip, "Action : Change Number"
 671				assert_equal(
 672					backend_report.strip,
 673					"[move backend?]: sgx -> sgx"
 674				)
 675				assert_equal(
 676					number_report.strip,
 677					"[change number?]: +15556667777 -> +12222222222"
 678				)
 679
 680				assert_mock Command::COMMAND_MANAGER
 681				assert_mock exe.customer_repo
 682				assert_mock AdminAction::NumberChange::REDIS
 683				assert_mock AdminActionRepo::REDIS
 684				assert_mock BackendSgx::REDIS
 685				assert_mock BackendSgx::IQ_MANAGER
 686				assert_mock bandwidth_tn_repo_mock
 687				assert_mock sgx
 688			}
 689		end
 690	end
 691	em :test_change_num_different_num_same_backend
 692
 693	def test_change_num_same_num_different_backend
 694		target_backend_sgx = "route_value"
 695
 696		bandwidth_tn_repo_mock = setup_bandwidth_tn_repo_mock(
 697			should_disconnect: false
 698		)
 699
 700		BandwidthTnRepo.stub :new, bandwidth_tn_repo_mock do
 701			execute_command { |exe|
 702				sgx = Minitest::Mock.new(OpenStruct.new(
 703					registered?: OpenStruct.new(phone: "+15556667777"),
 704					jid: Blather::JID.new(CONFIG[:sgx])
 705				))
 706
 707				target_customer = customer(sgx: sgx)
 708				admin = AdminCommand.for(target_customer, exe.customer_repo)
 709
 710				exe.customer_repo.expect(
 711					:find_by_jid,
 712					EMPromise.resolve(target_customer),
 713					[Matching.new do |jid|
 714						assert jid.is_a? Blather::JID
 715						assert_equal jid.stripped.to_s, "test@example.com"
 716					end]
 717				)
 718
 719				Command::COMMAND_MANAGER.expect(
 720					:write,
 721					EMPromise.resolve(
 722						change_number_form(
 723							new_backend: target_backend_sgx
 724						)
 725					),
 726					[Matching.new do |iq|
 727						assert_undoable_form(iq)
 728						assert_change_number_form(iq)
 729					end]
 730				)
 731
 732				BackendSgx::IQ_MANAGER.expect(
 733					:write,
 734					EMPromise.resolve(nil)
 735				) do |iq|
 736					assert_ibr_deregister_form(iq)
 737				end
 738
 739				BackendSgx::IQ_MANAGER.expect(
 740					:write,
 741					EMPromise.resolve(nil)
 742				) do |iq|
 743					assert_ibr_register_form(
 744						iq,
 745						"+15556667777",
 746						target_backend_sgx: target_backend_sgx,
 747						nick: "test_sgx_account",
 748						username: "test_sgx_user",
 749						password: "test_sgx_password"
 750					)
 751				end
 752
 753				AdminAction::NumberChange::REDIS.expect(
 754					:get,
 755					EMPromise.resolve(nil),
 756					["jmp_customer_backend_sgx-#{target_customer.customer_id}"]
 757				)
 758
 759				AdminAction::NumberChange::REDIS.expect(
 760					:set,
 761					EMPromise.resolve(nil),
 762					[
 763						"jmp_customer_backend_sgx-#{target_customer.customer_id}",
 764						"route_value"
 765					]
 766				)
 767
 768				AdminAction::NumberChange::REDIS.expect(
 769					:get,
 770					EMPromise.resolve("route_value"),
 771					["jmp_customer_backend_sgx-#{target_customer.customer_id}"]
 772				)
 773
 774				AdminAction::NumberChange::REDIS.expect(
 775					:exists,
 776					EMPromise.resolve(1),
 777					["catapult_jid-+15556667777"]
 778				)
 779
 780				BackendSgx::REDIS.expect(
 781					:set,
 782					EMPromise.resolve(nil),
 783					[
 784						"catapult_jid-+15556667777",
 785						"customer_test@component"
 786					]
 787				)
 788
 789				expected_xadd_args = {
 790					old_tel: "+15556667777",
 791					new_tel: "+15556667777",
 792					old_backend: "sgx",
 793					new_backend: "route_value",
 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 -> route_value"
 820				)
 821				assert_equal(
 822					number_report.strip,
 823					"[change number?]: +15556667777 -> +15556667777"
 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_same_num_different_backend
 838
 839	def test_change_num_different_num_different_backend
 840		old_tel = "+15556667777"
 841		new_tel = "+12222222222"
 842		target_backend_sgx = "route_value"
 843
 844		bandwidth_tn_repo_mock = setup_bandwidth_tn_repo_mock(
 845			should_disconnect: false
 846		)
 847
 848		BandwidthTnRepo.stub :new, bandwidth_tn_repo_mock do
 849			execute_command { |exe|
 850				sgx = Minitest::Mock.new(OpenStruct.new(
 851					registered?: OpenStruct.new(phone: old_tel),
 852					jid: Blather::JID.new(CONFIG[:sgx])
 853				))
 854
 855				target_customer = customer(sgx: sgx)
 856				admin = AdminCommand.for(target_customer, exe.customer_repo)
 857
 858				exe.customer_repo.expect(
 859					:find_by_jid,
 860					EMPromise.resolve(target_customer),
 861					[Matching.new do |jid|
 862						assert jid.is_a? Blather::JID
 863						assert_equal jid.stripped.to_s, "test@example.com"
 864					end]
 865				)
 866
 867				Command::COMMAND_MANAGER.expect(
 868					:write,
 869					EMPromise.resolve(
 870						change_number_form(
 871							new_tel: new_tel,
 872							new_backend: target_backend_sgx
 873						)
 874					),
 875					[Matching.new do |iq|
 876						assert_undoable_form(iq)
 877						assert_change_number_form(iq)
 878					end]
 879				)
 880
 881				BackendSgx::IQ_MANAGER.expect(
 882					:write,
 883					EMPromise.resolve(nil)
 884				) do |iq|
 885					assert_ibr_deregister_form(iq)
 886				end
 887
 888				BackendSgx::IQ_MANAGER.expect(
 889					:write,
 890					EMPromise.resolve(nil)
 891				) do |iq|
 892					assert_ibr_register_form(
 893						iq,
 894						"+12222222222",
 895						target_backend_sgx: target_backend_sgx,
 896						nick: "test_sgx_account",
 897						username: "test_sgx_user",
 898						password: "test_sgx_password"
 899					)
 900				end
 901
 902				AdminAction::NumberChange::REDIS.expect(
 903					:exists,
 904					EMPromise.resolve(1),
 905					["catapult_jid-#{old_tel}"]
 906				)
 907
 908				AdminAction::NumberChange::REDIS.expect(
 909					:rename,
 910					EMPromise.resolve(nil),
 911					["catapult_fwd-#{old_tel}", "catapult_fwd-#{new_tel}"]
 912				)
 913
 914				AdminAction::NumberChange::REDIS.expect(
 915					:get,
 916					EMPromise.resolve(nil),
 917					["jmp_customer_backend_sgx-test"]
 918				)
 919
 920				AdminAction::NumberChange::REDIS.expect(
 921					:set,
 922					EMPromise.resolve(nil),
 923					[
 924						"jmp_customer_backend_sgx-#{target_customer.customer_id}",
 925						"route_value"
 926					]
 927				)
 928
 929				AdminAction::NumberChange::REDIS.expect(
 930					:get,
 931					EMPromise.resolve("route_value"),
 932					["jmp_customer_backend_sgx-test"]
 933				)
 934
 935				BackendSgx::REDIS.expect(
 936					:set,
 937					EMPromise.resolve(nil),
 938					[
 939						"catapult_jid-#{new_tel}",
 940						"customer_test@component"
 941					]
 942				)
 943
 944				expected_xadd_args = {
 945					old_tel: "+15556667777",
 946					new_tel: "+12222222222",
 947					target_backend_sgx: "route_value",
 948					should_delete: nil,
 949					actor_id: "test",
 950					class: "NumberChange",
 951					direction: :forward
 952				}.freeze
 953
 954				AdminActionRepo::REDIS.expect(
 955					:xadd,
 956					EMPromise.resolve(nil)
 957				) do |admin_actions, star, **xadd_args|
 958					assert_equal admin_actions, "admin_actions"
 959					assert_equal star, "*"
 960
 961					xadd_args.each do |k, v|
 962						assert_equal v, expected_xadd_args[k]
 963					end
 964				end
 965
 966				result = admin.action_number_change.sync
 967
 968				slug, backend_report, number_report = result.lines
 969
 970				assert_equal slug.strip, "Action : Change Number"
 971				assert_equal(
 972					backend_report.strip,
 973					"[move backend?]: sgx -> route_value"
 974				)
 975				assert_equal(
 976					number_report.strip,
 977					"[change number?]: +15556667777 -> +12222222222"
 978				)
 979
 980				assert_mock Command::COMMAND_MANAGER
 981				assert_mock exe.customer_repo
 982				assert_mock AdminAction::NumberChange::REDIS
 983				assert_mock AdminActionRepo::REDIS
 984				assert_mock BackendSgx::REDIS
 985				assert_mock BackendSgx::IQ_MANAGER
 986				assert_mock bandwidth_tn_repo_mock
 987				assert_mock sgx
 988			}
 989		end
 990	end
 991	em :test_change_num_different_num_different_backend
 992
 993	def test_change_num_bandwidth_backend_with_delete_should_disconnect
 994		old_tel = "+15556667777"
 995		new_tel = "+12222222222"
 996
 997		bandwidth_tn_repo_mock = setup_bandwidth_tn_repo_mock(
 998			should_disconnect: true,
 999			old_tel: old_tel,
1000			new_tel: new_tel
1001		)
1002
1003		BandwidthTnRepo.stub :new, bandwidth_tn_repo_mock do
1004			execute_command { |exe|
1005				sgx = Minitest::Mock.new(OpenStruct.new(
1006					registered?: OpenStruct.new(phone: old_tel),
1007					jid: Blather::JID.new(CONFIG[:sgx])
1008				))
1009
1010				target_customer = customer(sgx: sgx)
1011				admin = AdminCommand.for(target_customer, exe.customer_repo)
1012
1013				exe.customer_repo.expect(
1014					:find_by_jid,
1015					EMPromise.resolve(customer(sgx: sgx)),
1016					[Matching.new do |jid|
1017						assert jid.is_a? Blather::JID
1018						assert_equal jid.stripped.to_s, "test@example.com"
1019					end]
1020				)
1021
1022				AdminAction::NumberChange::REDIS.expect(
1023					:exists,
1024					EMPromise.resolve(1),
1025					["catapult_jid-#{old_tel}"]
1026				)
1027
1028				AdminAction::NumberChange::REDIS.expect(
1029					:rename,
1030					EMPromise.resolve(nil),
1031					["catapult_fwd-#{old_tel}", "catapult_fwd-#{new_tel}"]
1032				)
1033
1034				expected_xadd_args = {
1035					customer_id: "test",
1036					old_tel: old_tel,
1037					new_tel: new_tel,
1038					should_delete: "true",
1039					actor_id: "test",
1040					class: "NumberChange",
1041					direction: :forward
1042				}.freeze
1043
1044				AdminActionRepo::REDIS.expect(
1045					:xadd,
1046					EMPromise.resolve(nil)
1047				) do |admin_actions, star, **xadd_args|
1048					assert_equal admin_actions, "admin_actions"
1049					assert_equal star, "*"
1050
1051					xadd_args.each do |k, v|
1052						assert_equal v, expected_xadd_args[k]
1053					end
1054				end
1055
1056				Command::COMMAND_MANAGER.expect(
1057					:write,
1058					EMPromise.resolve(
1059						change_number_form(
1060							new_tel: new_tel,
1061							should_delete: true
1062						)
1063					),
1064					[Matching.new do |iq|
1065						assert_undoable_form(iq)
1066						assert_change_number_form(iq)
1067					end]
1068				)
1069
1070				AdminAction::NumberChange::REDIS.expect(
1071					:get,
1072					EMPromise.resolve(nil),
1073					["jmp_customer_backend_sgx-test"]
1074				)
1075
1076				AdminAction::NumberChange::REDIS.expect(
1077					:del,
1078					EMPromise.resolve(nil),
1079					["jmp_customer_backend_sgx-test"]
1080				)
1081
1082				AdminAction::NumberChange::REDIS.expect(
1083					:get,
1084					EMPromise.resolve(nil),
1085					["jmp_customer_backend_sgx-test"]
1086				)
1087
1088				BackendSgx::REDIS.expect(
1089					:set,
1090					EMPromise.resolve(nil),
1091					[
1092						"catapult_jid-#{new_tel}",
1093						"customer_test@component"
1094					]
1095				)
1096
1097				BackendSgx::IQ_MANAGER.expect(
1098					:write,
1099					EMPromise.resolve(nil)
1100				) do |iq|
1101					assert_ibr_deregister_form(iq)
1102				end
1103
1104				BackendSgx::IQ_MANAGER.expect(
1105					:write,
1106					EMPromise.resolve(nil)
1107				) do |iq|
1108					assert_ibr_register_form(
1109						iq,
1110						new_tel,
1111						nick: "test_bw_account",
1112						username: "test_bw_user",
1113						password: "test_bw_password"
1114					)
1115				end
1116
1117				result = admin.action_number_change.sync
1118
1119				slug, backend_report, number_report = result.lines
1120
1121				assert_equal slug.strip, "Action : Change Number"
1122				assert_equal(
1123					backend_report.strip,
1124					"[move backend?]: sgx -> sgx"
1125				)
1126				assert_equal(
1127					number_report.strip,
1128					"[change number?]: #{old_tel} -> #{new_tel}"
1129				)
1130
1131				assert_mock Command::COMMAND_MANAGER
1132				assert_mock exe.customer_repo
1133				assert_mock AdminAction::NumberChange::REDIS
1134				assert_mock AdminActionRepo::REDIS
1135				assert_mock BackendSgx::REDIS
1136				assert_mock BackendSgx::IQ_MANAGER
1137				assert_mock bandwidth_tn_repo_mock
1138				assert_mock sgx
1139			}
1140		end
1141	end
1142	em :test_change_num_bandwidth_backend_with_delete_should_disconnect
1143
1144	def test_change_num_non_bw_backend_should_not_disconnect
1145		old_tel = "+15556667777"
1146		new_tel = "+12222222222"
1147		non_bw_backend = "route_value"
1148
1149		bandwidth_tn_repo_mock = setup_bandwidth_tn_repo_mock(
1150			should_disconnect: false
1151		)
1152
1153		BandwidthTnRepo.stub :new, bandwidth_tn_repo_mock do
1154			execute_command { |exe|
1155				Command::COMMAND_MANAGER.expect(
1156					:write,
1157					EMPromise.resolve(change_number_form(new_tel: new_tel)),
1158					[Matching.new do |iq|
1159						assert_undoable_form(iq)
1160						assert_change_number_form(iq)
1161					end]
1162				)
1163
1164				non_bandwidth_sgx = Minitest::Mock.new(OpenStruct.new(
1165					registered?: OpenStruct.new(phone: old_tel),
1166					jid: Blather::JID.new(non_bw_backend)
1167				))
1168
1169				target_customer = customer(sgx: non_bandwidth_sgx)
1170				admin = AdminCommand.for(target_customer, exe.customer_repo)
1171
1172				exe.customer_repo.expect(
1173					:find_by_jid,
1174					EMPromise.resolve(target_customer),
1175					[Blather::JID.new("test@example.com")]
1176				)
1177
1178				AdminAction::NumberChange::REDIS.expect(
1179					:exists,
1180					EMPromise.resolve(1),
1181					["catapult_jid-+15556667777"]
1182				)
1183
1184				AdminAction::NumberChange::REDIS.expect(
1185					:rename,
1186					EMPromise.resolve(nil),
1187					["catapult_fwd-#{old_tel}", "catapult_fwd-#{new_tel}"]
1188				)
1189
1190				AdminAction::NumberChange::REDIS.expect(
1191					:get,
1192					EMPromise.resolve("route_value"),
1193					["jmp_customer_backend_sgx-#{target_customer.customer_id}"]
1194				)
1195
1196				BackendSgx::IQ_MANAGER.expect(
1197					:write,
1198					EMPromise.resolve(nil)
1199				) do |iq|
1200					assert_ibr_deregister_form(
1201						iq,
1202						target_backend_sgx: "route_value"
1203					)
1204				end
1205
1206				AdminAction::NumberChange::REDIS.expect(
1207					:set,
1208					EMPromise.resolve(nil),
1209					[
1210						"jmp_customer_backend_sgx-#{target_customer.customer_id}",
1211						"route_value"
1212					]
1213				)
1214
1215				AdminAction::NumberChange::REDIS.expect(
1216					:get,
1217					EMPromise.resolve("route_value"),
1218					["jmp_customer_backend_sgx-#{target_customer.customer_id}"]
1219				)
1220
1221				BackendSgx::IQ_MANAGER.expect(
1222					:write,
1223					EMPromise.resolve(nil)
1224				) do |iq|
1225					assert_ibr_register_form(
1226						iq,
1227						"+12222222222",
1228						nick: "test_sgx_account",
1229						username: "test_sgx_user",
1230						password: "test_sgx_password",
1231						target_backend_sgx: "route_value"
1232					)
1233				end
1234
1235				BackendSgx::REDIS.expect(
1236					:set,
1237					EMPromise.resolve(nil),
1238					["catapult_jid-+12222222222", "customer_test@component"]
1239				)
1240
1241				expected_xadd_args = {
1242					customer_id: "test",
1243					old_tel: old_tel,
1244					new_tel: new_tel,
1245					should_delete: "true",
1246					actor_id: "test",
1247					class: "NumberChange",
1248					direction: :forward
1249				}.freeze
1250
1251				AdminActionRepo::REDIS.expect(
1252					:xadd,
1253					EMPromise.resolve(nil)
1254				) do |admin_actions, star, **xadd_args|
1255					assert_equal admin_actions, "admin_actions"
1256					assert_equal star, "*"
1257
1258					xadd_args.each do |k, v|
1259						assert_equal v, expected_xadd_args[k]
1260					end
1261				end
1262
1263				result = admin.action_number_change.sync
1264
1265				slug, backend_report, number_report = result.lines
1266
1267				assert_equal slug.strip, "Action : Change Number"
1268				assert_equal(
1269					backend_report.strip,
1270					"[move backend?]: #{non_bw_backend} -> #{non_bw_backend}"
1271				)
1272				assert_equal(
1273					number_report.strip,
1274					"[change number?]: +15556667777 -> +12222222222"
1275				)
1276
1277				assert_mock Command::COMMAND_MANAGER
1278				assert_mock exe.customer_repo
1279				assert_mock AdminAction::NumberChange::REDIS
1280				assert_mock AdminActionRepo::REDIS
1281				assert_mock BackendSgx::REDIS
1282				assert_mock BackendSgx::IQ_MANAGER
1283				assert_mock bandwidth_tn_repo_mock
1284				assert_mock non_bandwidth_sgx
1285			}
1286		end
1287	end
1288	em :test_change_num_non_bw_backend_should_not_disconnect
1289end