11using BTCPayServer . Rating ;
22using BTCPayServer . Services . Rates ;
3+ using BTCPayServer . Tests ;
34using BTCPayServer . Tests . Mocks ;
45
56using Xunit ;
@@ -9,6 +10,87 @@ namespace BTCPayServer.Plugins.IntegrationTests.Monero;
910
1011public class MoneroPluginIntegrationTest ( ITestOutputHelper helper ) : MoneroAndBitcoinIntegrationTestBase ( helper )
1112{
13+ #region Methods
14+
15+ private async Task CreateWalletViaForm (
16+ PlaywrightTester s ,
17+ string walletName ,
18+ string address ,
19+ string viewKey ,
20+ string password ,
21+ string restoreHeight )
22+ {
23+ await s . Page . FillAsync ( "input#WalletName" , walletName ) ;
24+ await s . Page . FillAsync ( "input#PrimaryAddress" , address ) ;
25+ await s . Page . FillAsync ( "input#PrivateViewKey" , viewKey ) ;
26+ await s . Page . FillAsync ( "input#WalletPassword" , password ) ;
27+ await s . Page . FillAsync ( "input#RestoreHeight" , restoreHeight ) ;
28+ await s . Page . ClickAsync ( "button[name='command'][value='connect-wallet']" ) ;
29+ await s . Page . Locator ( $ ".wallet-card[data-wallet='{ walletName } ']") . WaitForAsync ( ) ;
30+ }
31+
32+ private async Task CreateWalletViaModal (
33+ PlaywrightTester s ,
34+ string walletName ,
35+ string address ,
36+ string viewKey ,
37+ string password ,
38+ string restoreHeight )
39+ {
40+ await s . Page . FillAsync ( "#createWalletModal input#WalletName" , walletName ) ;
41+ await s . Page . FillAsync ( "#createWalletModal input#PrimaryAddress" , address ) ;
42+ await s . Page . FillAsync ( "#createWalletModal input#PrivateViewKey" , viewKey ) ;
43+ await s . Page . FillAsync ( "#createWalletModal input#WalletPassword" , password ) ;
44+ await s . Page . FillAsync ( "#createWalletModal input#RestoreHeight" , restoreHeight ) ;
45+ await s . Page . ClickAsync ( "#createWalletModal button[name='command'][value='replace-wallet']" ) ;
46+ await s . Page . Locator ( $ ".wallet-card[data-wallet='{ walletName } ']") . WaitForAsync ( ) ;
47+
48+ }
49+
50+ private async Task < bool > WalletExists ( PlaywrightTester s , string walletName )
51+ {
52+ var walletCard = s . Page . Locator ( $ ".wallet-card[data-wallet='{ walletName } ']") ;
53+ try
54+ {
55+ await walletCard . WaitForAsync ( ) ;
56+ return true ;
57+ }
58+ catch
59+ {
60+ return false ;
61+ }
62+ }
63+
64+ private async Task SwitchActiveWallet ( PlaywrightTester s , string walletName , string password )
65+ {
66+ var walletCard = s . Page . Locator ( $ ".wallet-card[data-wallet='{ walletName } ']") ;
67+ await walletCard . Locator ( ".wallet-card-content" ) . ClickAsync ( ) ;
68+ await s . Page . Locator ( "input#ActiveWalletPassword" ) . WaitForAsync ( ) ;
69+ await s . Page . FillAsync ( "input#ActiveWalletPassword" , password ) ;
70+ await s . Page . ClickAsync ( "button[name='command'][value='set-active-wallet']" ) ;
71+ await s . Page . Locator ( $ ".wallet-card[data-wallet='{ walletName } '].wallet-card-active") . WaitForAsync ( ) ;
72+ }
73+
74+ private async Task DeleteWallet ( PlaywrightTester s , string walletName )
75+ {
76+ var walletCard = s . Page . Locator ( $ ".wallet-card[data-wallet='{ walletName } ']") ;
77+ await walletCard . Locator ( ".wallet-actions .dropdown-toggle" ) . ClickAsync ( ) ;
78+ await walletCard . Locator ( ".wallet-action-delete" ) . WaitForAsync ( ) ;
79+ await walletCard . Locator ( ".wallet-action-delete" ) . ClickAsync ( ) ;
80+ await s . Page . Locator ( "#deleteWalletModal" ) . WaitForAsync ( ) ;
81+ await s . Page . ClickAsync ( "#deleteWalletModal button[name='command'][value='delete-wallets']" ) ;
82+ await walletCard . WaitForAsync ( new ( ) { State = Microsoft . Playwright . WaitForSelectorState . Detached } ) ;
83+ }
84+
85+ private async Task < bool > WalletIsActive ( PlaywrightTester s , string walletName )
86+ {
87+ var walletCard = s . Page . Locator ( $ ".wallet-card[data-wallet='{ walletName } ']") ;
88+ var hasActiveClass = await walletCard . GetAttributeAsync ( "class" ) ;
89+ return hasActiveClass ? . Contains ( "wallet-card-active" ) ?? false ;
90+ }
91+
92+ #endregion
93+
1294 [ Fact ]
1395 public async Task EnableMoneroPluginSuccessfully ( )
1496 {
@@ -36,61 +118,71 @@ public async Task EnableMoneroPluginSuccessfully()
36118 await s . RegisterNewUser ( true ) ;
37119 await s . CreateNewStore ( preferredExchange : "Kraken" ) ;
38120 await s . Page . Locator ( "a.nav-link[href*='monerolike/XMR']" ) . ClickAsync ( ) ;
39- await s . Page . Locator ( "input#PrimaryAddress" ) . FillAsync ( "43Pnj6ZKGFTJhaLhiecSFfLfr64KPJZw7MyGH73T6PTDekBBvsTAaWEUSM4bmJqDuYLizhA13jQkMRPpz9VXBCBqQQb6y5L" ) ;
40- await s . Page . Locator ( "input#PrivateViewKey" ) . FillAsync ( "1bfa03b0c78aa6bc8292cf160ec9875657d61e889c41d0ebe5c54fd3a2c4b40e" ) ;
41- await s . Page . Locator ( "input#RestoreHeight" ) . FillAsync ( "0" ) ;
42- await s . Page . Locator ( "input#WalletPassword" ) . FillAsync ( "pass123" ) ;
43- await s . Page . ClickAsync ( "button[name='command'][value='set-wallet-details']" ) ;
121+ await s . Page . Locator ( "text=No Wallet Configured" ) . WaitForAsync ( ) ;
122+ await s . Page . ClickAsync ( "a[href*='/connect/XMR']" ) ;
123+ await s . Page . Locator ( "input#WalletName" ) . WaitForAsync ( ) ;
124+ await CreateWalletViaForm (
125+ s ,
126+ walletName : "primary-wallet" ,
127+ address : "43Pnj6ZKGFTJhaLhiecSFfLfr64KPJZw7MyGH73T6PTDekBBvsTAaWEUSM4bmJqDuYLizhA13jQkMRPpz9VXBCBqQQb6y5L" ,
128+ viewKey : "1bfa03b0c78aa6bc8292cf160ec9875657d61e889c41d0ebe5c54fd3a2c4b40e" ,
129+ password : "pass123" ,
130+ restoreHeight : "0"
131+ ) ;
132+ Assert . True ( await WalletExists ( s , "primary-wallet" ) ) ;
133+ Assert . True ( await WalletIsActive ( s , "primary-wallet" ) ) ;
134+
44135 await s . Page . CheckAsync ( "#Enabled" ) ;
45136 await s . Page . SelectOptionAsync ( "#SettlementConfirmationThresholdChoice" , "2" ) ;
46137 await s . Page . ClickAsync ( "#SaveButton" ) ;
47- var classList = await s . Page . Locator ( "svg.icon-checkmark" ) . GetAttributeAsync ( "class" ) ;
48- Assert . Contains ( "text-success" , classList ) ;
49-
50- // Set rate provider
51- await s . Page . Locator ( "#StoreNav-General" ) . ClickAsync ( ) ;
52- await s . Page . Locator ( "#mainNav #StoreNav-Rates" ) . ClickAsync ( ) ;
53- await s . Page . FillAsync ( "#DefaultCurrencyPairs" , "BTC_USD,XMR_USD,XMR_BTC" ) ;
54- await s . Page . SelectOptionAsync ( "#PrimarySource_PreferredExchange" , "kraken" ) ;
55- await s . Page . Locator ( "#page-primary" ) . ClickAsync ( ) ;
56-
57- // Generate a new invoice
58- await s . Page . Locator ( "a.nav-link[href*='invoices']" ) . ClickAsync ( ) ;
59- await s . Page . Locator ( "#page-primary" ) . ClickAsync ( ) ;
60- await s . Page . FillAsync ( "#Amount" , "4.20" ) ;
61- await s . Page . FillAsync ( "#BuyerEmail" , "monero@monero.com" ) ;
62- await Task . Delay ( TimeSpan . FromSeconds ( 25 ) ) ; // wallet-rpc needs some time to sync. refactor this later
63- await s . Page . Locator ( "#page-primary" ) . ClickAsync ( ) ;
64-
65- // View the invoice
66- var href = await s . Page . Locator ( "a[href^='/i/']" ) . GetAttributeAsync ( "href" ) ;
67- var invoiceId = href ? . Split ( "/i/" ) . Last ( ) ;
68- await s . Page . Locator ( $ "a[href='/i/{ invoiceId } ']") . ClickAsync ( ) ;
69- await s . Page . ClickAsync ( "#DetailsToggle" ) ;
70-
71- // Verify the total fiat amount is $4.20
72- var totalFiat = await s . Page . Locator ( "#PaymentDetails-TotalFiat dd.clipboard-button" ) . InnerTextAsync ( ) ;
73- Assert . Equal ( "$4.20" , totalFiat ) ;
74-
75- await s . Page . GoBackAsync ( ) ;
138+ await s . Page . Locator ( "svg.icon-checkmark.text-success" ) . WaitForAsync ( ) ;
139+
140+ var invoiceId = await s . CreateInvoice ( s . StoreId , 10 , "USD" ) ;
141+ await s . GoToInvoiceCheckout ( invoiceId ) ;
142+
143+ var copyButton = s . Page . Locator ( "button[data-clipboard].clipboard-button" ) ;
144+ var moneroAddress = await copyButton . GetAttributeAsync ( "data-clipboard" ) ;
145+ Assert . NotNull ( moneroAddress ) ;
146+ Assert . True ( moneroAddress . StartsWith ( "8" ) , $ "Expected Monero address to start with 8, but got: { moneroAddress } ") ;
147+
148+ await s . GoToStore ( s . StoreId ) ;
76149 await s . Page . Locator ( "a.nav-link[href*='monerolike/XMR']" ) . ClickAsync ( ) ;
150+ Assert . True ( await WalletIsActive ( s , "primary-wallet" ) ) ;
77151
78- // Create a new account label
79- await s . Page . FillAsync ( "#NewAccountLabel" , "tst-account" ) ;
80- await s . Page . ClickAsync ( "button[name='command'][value='add-account']" ) ;
81-
82- // Select primary Account Index
83- await s . Page . Locator ( "a.nav-link[href*='monerolike/XMR']" ) . ClickAsync ( ) ;
84- await s . Page . SelectOptionAsync ( "#AccountIndex" , "1" ) ;
152+ await s . Page . CheckAsync ( "#Enabled" ) ;
153+ await s . Page . SelectOptionAsync ( "#SettlementConfirmationThresholdChoice" , "3" ) ;
85154 await s . Page . ClickAsync ( "#SaveButton" ) ;
86-
87- // Verify selected account index
155+
156+ await s . GoToStore ( s . StoreId ) ;
88157 await s . Page . Locator ( "a.nav-link[href*='monerolike/XMR']" ) . ClickAsync ( ) ;
89- var selectedValue = await s . Page . Locator ( "#AccountIndex" ) . InputValueAsync ( ) ;
90- Assert . Equal ( "1" , selectedValue ) ;
158+ await s . Page . Locator ( "#walletManagementMenu" ) . WaitForAsync ( ) ;
159+
160+ Assert . True ( await WalletExists ( s , "primary-wallet" ) ) ;
161+ Assert . True ( await WalletIsActive ( s , "primary-wallet" ) ) ;
162+ await s . Page . ClickAsync ( "#walletManagementMenu" ) ;
163+ await s . Page . ClickAsync ( "button[data-bs-target='#createWalletModal']" ) ;
164+ await s . Page . Locator ( "#createWalletModal input#WalletName" ) . WaitForAsync ( ) ;
165+
166+ await CreateWalletViaModal (
167+ s ,
168+ walletName : "secondary-wallet" ,
169+ address : "41u3R13W1UDhvHGNS1cqtoh4CKFkuZ5aWbkmkEskhm3SNsuaLQAeFtrXyd6Q2XAgwzf41CMC65u8fVWjB38RLAUb8AKJMw9" ,
170+ viewKey : "134af10334bd65ce91e015db3ea9f0b1abd1a9ed2fa378bc537498f4f52f6f0f" ,
171+ password : "pass456" ,
172+ restoreHeight : "100"
173+ ) ;
174+ Assert . True ( await WalletExists ( s , "primary-wallet" ) ) ;
175+ Assert . True ( await WalletExists ( s , "secondary-wallet" ) ) ;
176+ Assert . True ( await WalletIsActive ( s , "secondary-wallet" ) ) ;
177+
178+ await SwitchActiveWallet ( s , "primary-wallet" , "pass123" ) ;
179+ Assert . True ( await WalletIsActive ( s , "primary-wallet" ) ) ;
180+ Assert . False ( await WalletIsActive ( s , "secondary-wallet" ) ) ;
181+
182+ await DeleteWallet ( s , "secondary-wallet" ) ;
183+ Assert . True ( await WalletExists ( s , "primary-wallet" ) ) ;
184+ Assert . False ( await WalletExists ( s , "secondary-wallet" ) ) ;
185+ Assert . True ( await WalletIsActive ( s , "primary-wallet" ) ) ;
91186
92- // Select confirmation time to 0
93- await s . Page . SelectOptionAsync ( "#SettlementConfirmationThresholdChoice" , "3" ) ;
94- await s . Page . ClickAsync ( "#SaveButton" ) ;
95187 }
96- }
188+ }
0 commit comments