feat: integrate Just Works app and native business setup
Preserve hosted website UX inside Archipelago, add isolated Business and owner-authorized native wallet setup, and include deployment handoff. Based on main with native signer import already accepted.
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
import unittest
|
||||
import http.client
|
||||
import threading
|
||||
from http.server import ThreadingHTTPServer
|
||||
import server
|
||||
from unittest.mock import patch
|
||||
from urllib.error import HTTPError
|
||||
import payments
|
||||
|
||||
BODY = {'siteId':'bakery', 'address':'mywallet@minibits.cash', 'credentials':{'ownerIdentifier':'owner', 'ownerPassword':'fake-test-password'}}
|
||||
def record(address='mywallet@minibits.cash'):
|
||||
return {'id':'bakery', 'nsite':{'deploymentStatus':'published'}, 'identity':{'profile':{'lud16':address}}}
|
||||
|
||||
class PaymentTests(unittest.TestCase):
|
||||
def test_saves_only_address_and_checks_published_destination(self):
|
||||
replies = [{'nsite':{'id':'bakery'}}, {}, {'artifact':{'verified':True}, 'nsite':record()}, {'nsite':record()}]
|
||||
with patch('payments.request_core', side_effect=replies) as call:
|
||||
result = payments.connect_payment(BODY)
|
||||
self.assertTrue(result['verified'])
|
||||
update = call.call_args_list[1]
|
||||
self.assertEqual(update.args[:2], ('PATCH','/api/nsites/bakery'))
|
||||
self.assertEqual(set(update.args[2]), {'payment','ownerIdentifier','ownerPassword'})
|
||||
self.assertEqual(update.args[2]['payment'], BODY['address'])
|
||||
self.assertEqual(call.call_args_list[-1].args, ('GET','/api/nsites/bakery'))
|
||||
self.assertNotIn('password', str(result))
|
||||
|
||||
def test_rejected_owner_never_changes_or_publishes(self):
|
||||
with patch('payments.request_core', side_effect=HTTPError('https://justworks.cash',401,'unauthorized',{},None)) as call:
|
||||
with self.assertRaises(HTTPError): payments.connect_payment(BODY)
|
||||
self.assertEqual(call.call_count,1)
|
||||
|
||||
def test_wrong_website_owner_never_changes(self):
|
||||
with patch('payments.request_core', return_value={'nsite':{'id':'other'}}) as call:
|
||||
with self.assertRaises(ValueError): payments.connect_payment(BODY)
|
||||
self.assertEqual(call.call_count,1)
|
||||
|
||||
def test_partial_publish_and_wrong_destination_never_succeed(self):
|
||||
for deploy, public in [({}, {'nsite':record()}),
|
||||
({'artifact':{'verified':True},'nsite':record('other@minibits.cash')},{'nsite':record()}),
|
||||
({'artifact':{'verified':True},'nsite':record()},{'nsite':record('other@minibits.cash')}),
|
||||
(OSError('timeout'), {})]:
|
||||
with self.subTest(deploy=deploy), patch('payments.request_core', side_effect=[{'nsite':{'id':'bakery'}},{},deploy,public]):
|
||||
with self.assertRaises(payments.PublishUnverified): payments.connect_payment(BODY)
|
||||
|
||||
def test_invalid_input_never_reaches_upstream(self):
|
||||
for body in [None, {}, {**BODY,'siteId':'../admin'}, {**BODY,'address':'someone@evil.test'}, {**BODY,'credentials':{}}, {**BODY,'credentials':{'ownerKey':['invalid']}}]:
|
||||
with self.subTest(body=body), patch('payments.request_core') as call:
|
||||
with self.assertRaises(ValueError): payments.connect_payment(body)
|
||||
call.assert_not_called()
|
||||
|
||||
def test_concurrent_updates_are_rejected_without_writes(self):
|
||||
with payments.LOCK, patch('payments.request_core') as call:
|
||||
with self.assertRaises(ValueError): payments.connect_payment(BODY)
|
||||
call.assert_not_called()
|
||||
|
||||
class PaymentHttpTests(unittest.TestCase):
|
||||
def test_post_requires_exact_origin_json_and_bounded_body(self):
|
||||
httpd = ThreadingHTTPServer(('127.0.0.1', 0), server.Handler)
|
||||
worker = threading.Thread(target=httpd.serve_forever, daemon=True); worker.start()
|
||||
host = f'127.0.0.1:{httpd.server_port}'
|
||||
try:
|
||||
with patch('server.connect_payment', return_value={'verified':True}) as connect:
|
||||
for origin, content_type, body, expected in [
|
||||
('https://evil.test','application/json','{}',403),
|
||||
('','application/json','{}',403),
|
||||
('http://'+host,'text/plain','{}',415),
|
||||
('http://'+host,'application/json','x'*8193,413),
|
||||
('http://'+host,'application/json','{}',200)]:
|
||||
client = http.client.HTTPConnection(host)
|
||||
client.request('POST','/api/payment-connect',body,{'Origin':origin,'Content-Type':content_type})
|
||||
response=client.getresponse(); self.assertEqual(response.status,expected); response.read(); client.close()
|
||||
self.assertEqual(connect.call_count,1)
|
||||
finally:
|
||||
httpd.shutdown(); httpd.server_close(); worker.join()
|
||||
|
||||
if __name__ == '__main__': unittest.main()
|
||||
Reference in New Issue
Block a user