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