2828
2929
3030WALLET_NAME = "receive_requests"
31+ SECOND_WALLET_NAME = "receive_requests_alt"
32+
33+
34+ def wait_until (predicate , timeout = 20 , interval = 0.1 , description = "condition" ):
35+ deadline = time .time () + timeout
36+ last_error = None
37+ while time .time () < deadline :
38+ try :
39+ if predicate ():
40+ return
41+ except Exception as err : # noqa: BLE001 - test polling should tolerate transient state
42+ last_error = err
43+ time .sleep (interval )
44+ if last_error :
45+ raise AssertionError (f"Timed out waiting for { description } : { last_error } " )
46+ raise AssertionError (f"Timed out waiting for { description } " )
3147
3248
3349def _stop_gui (harness ):
@@ -69,15 +85,14 @@ def _relaunch_gui(harness):
6985 harness .driver = QmlDriver (harness .socket_path , timeout = GUI_STARTUP_TIMEOUT )
7086
7187
72- def _import_wallet (harness ):
73- harness .start_source_node ()
74- backup_path = os .path .join (harness .tmpdir , f"{ WALLET_NAME } .bak" )
75- rpc_call (harness .source_rpc_port , "createwallet" , {"wallet_name" : WALLET_NAME })
76- rpc_call (harness .source_rpc_port , "backupwallet" , [backup_path ], wallet = WALLET_NAME )
77- harness .stop_source_node ()
88+ def _create_wallet_backup (harness , wallet_name ):
89+ backup_path = os .path .join (harness .tmpdir , f"{ wallet_name } .bak" )
90+ rpc_call (harness .source_rpc_port , "createwallet" , {"wallet_name" : wallet_name })
91+ rpc_call (harness .source_rpc_port , "backupwallet" , [backup_path ], wallet = wallet_name )
92+ return backup_path
7893
79- harness . start_gui ()
80- gui = harness . driver
94+
95+ def _import_wallet_backup ( gui , backup_path , wallet_name ):
8196 gui .wait_for_property ("walletBadge" , "loading" , False , timeout_ms = 20000 )
8297 gui .click ("walletBadge" )
8398 try :
@@ -92,10 +107,63 @@ def _import_wallet(harness):
92107 gui .click ("importWalletChooseFileButton" )
93108 gui .wait_for_page ("importWalletSuccessPage" , timeout_ms = 30000 )
94109 gui .click ("importWalletSuccessOverviewButton" )
95- gui .wait_for_property ("walletBadge" , "text" , WALLET_NAME , timeout_ms = 20000 )
110+ gui .wait_for_property ("walletBadge" , "text" , wallet_name , timeout_ms = 20000 )
111+
112+
113+ def _import_wallets (harness ):
114+ harness .start_source_node ()
115+ primary_backup_path = _create_wallet_backup (harness , WALLET_NAME )
116+ secondary_backup_path = _create_wallet_backup (harness , SECOND_WALLET_NAME )
117+ harness .stop_source_node ()
118+
119+ harness .start_gui ()
120+ gui = harness .driver
121+ _import_wallet_backup (gui , primary_backup_path , WALLET_NAME )
122+ _import_wallet_backup (gui , secondary_backup_path , SECOND_WALLET_NAME )
123+ _select_wallet (gui , WALLET_NAME )
96124 return gui
97125
98126
127+ def _select_wallet (gui , wallet_name ):
128+ gui .wait_for_property ("walletBadge" , "loading" , False , timeout_ms = 20000 )
129+ if gui .get_property ("walletBadge" , "text" ) == wallet_name :
130+ return
131+
132+ gui .click ("walletBadge" )
133+ gui .wait_for_property ("walletSelectPopup" , "opened" , True , timeout_ms = 5000 )
134+
135+ def read_wallet_picker_rows ():
136+ wallet_count = gui .get_property ("walletSelectList" , "count" )
137+ rows = []
138+ for row_index in range (wallet_count ):
139+ try :
140+ rows .append (gui .get_list_item_property ("walletSelectList" , row_index , "text" ))
141+ except QmlDriverError :
142+ return None
143+ return rows
144+
145+ picker_state = {}
146+
147+ def wallet_picker_ready ():
148+ rows = read_wallet_picker_rows ()
149+ if rows is None :
150+ return False
151+ picker_state ["rows" ] = rows
152+ return True
153+
154+ wait_until (wallet_picker_ready , timeout = 10 , description = "wallet picker rows" )
155+
156+ for row_index , row_wallet_name in enumerate (picker_state ["rows" ]):
157+ if row_wallet_name == wallet_name :
158+ gui .click_list_item ("walletSelectList" , row_index )
159+ gui .wait_for_property ("walletBadge" , "text" , wallet_name , timeout_ms = 10000 )
160+ gui .wait_for_property ("walletSelectPopup" , "opened" , False , timeout_ms = 5000 )
161+ gui .settle (timeout_ms = 5000 )
162+ return
163+
164+ raise AssertionError (f"Wallet { wallet_name !r} not found in wallet picker" )
165+
166+
99167def _open_receive (gui ):
100168 gui .click ("receiveTabButton" )
101169 gui .wait_for_page ("requestPaymentPage" , timeout_ms = 10000 )
@@ -192,7 +260,7 @@ def run_test():
192260 harness = WalletFlowHarness ("qml_receive_requests" , port_offset = 70 )
193261 try :
194262 print ("[qml_receive_requests] starting" )
195- gui = _import_wallet (harness )
263+ gui = _import_wallets (harness )
196264 _open_receive (gui )
197265
198266 # Create first request — verify QR is available from the generated-state button.
@@ -262,6 +330,17 @@ def run_test():
262330 gui .click ("paymentRequestDetailEdit" )
263331 gui .wait_for_page ("requestPaymentPage" , timeout_ms = 10000 )
264332 gui .wait_for_property ("requestPaymentTitle" , "text" , "Payment request #1" , timeout_ms = 10000 )
333+ gui .click ("activityTabButton" )
334+ gui .wait_for_page ("paymentRequestDetailPage" , timeout_ms = 10000 )
335+ gui .wait_for_property ("paymentRequestDetailBack" , "visible" , True , timeout_ms = 10000 )
336+ gui .click ("paymentRequestDetailBack" )
337+ gui .wait_for_property ("activityDetailsPaymentRequestsSection" , "visible" , True , timeout_ms = 10000 )
338+ gui .wait_for_property ("activityDetailsPaymentRequest_0" , "visible" , True , timeout_ms = 10000 )
339+ gui .click ("activityDetailsPaymentRequest_0" )
340+ gui .wait_for_page ("paymentRequestDetailPage" , timeout_ms = 10000 )
341+ _select_wallet (gui , SECOND_WALLET_NAME )
342+ gui .click ("activityTabButton" )
343+ gui .wait_for_property ("activitySearchToggle" , "visible" , True , timeout_ms = 10000 )
265344 print ("[qml_receive_requests] fulfilled transaction links to payment request detail" )
266345
267346 # Restart and verify persistence
0 commit comments