2019-05-12 10:13:26 +02:00
using System ;
using Xunit ;
using OpenQA.Selenium ;
using OpenQA.Selenium.Chrome ;
using BTCPayServer.Tests.Logging ;
using Xunit.Abstractions ;
using OpenQA.Selenium.Interactions ;
using System.Linq ;
2019-05-13 10:59:15 +02:00
using NBitcoin ;
2019-05-12 10:13:26 +02:00
namespace BTCPayServer.Tests
{
2019-05-13 11:42:20 +02:00
[Trait("Selenium", "Selenium")]
public class ChromeTests
2019-05-12 10:13:26 +02:00
{
2019-05-13 11:42:20 +02:00
public ChromeTests ( ITestOutputHelper helper )
2019-05-12 10:13:26 +02:00
{
Logs . Tester = new XUnitLog ( helper ) { Name = "Tests" } ;
Logs . LogProvider = new XUnitLogProvider ( helper ) ;
}
2019-05-13 10:59:15 +02:00
[Fact]
public void CanNavigateServerSettings ( )
{
2019-05-13 11:42:20 +02:00
using ( var s = SeleniumTester . Create ( ) )
2019-05-13 10:59:15 +02:00
{
2019-05-13 11:42:20 +02:00
s . Start ( ) ;
s . RegisterNewUser ( true ) ;
s . Driver . FindElement ( By . Id ( "ServerSettings" ) ) . Click ( ) ;
s . Driver . AssertNoError ( ) ;
s . ClickOnAllSideMenus ( ) ;
s . Driver . Quit ( ) ;
}
2019-05-13 10:59:15 +02:00
}
2019-05-12 10:13:26 +02:00
[Fact]
public void NewUserLogin ( )
{
2019-05-13 11:42:20 +02:00
using ( var s = SeleniumTester . Create ( ) )
2019-05-12 10:13:26 +02:00
{
2019-05-13 11:42:20 +02:00
s . Start ( ) ;
2019-05-12 10:13:26 +02:00
//Register & Log Out
2019-05-13 11:42:20 +02:00
var email = s . RegisterNewUser ( ) ;
s . Driver . FindElement ( By . Id ( "Logout" ) ) . Click ( ) ;
s . Driver . AssertNoError ( ) ;
2019-05-14 16:33:46 +02:00
s . Driver . FindElement ( By . Id ( "Login" ) ) . Click ( ) ;
s . Driver . AssertNoError ( ) ;
2019-05-13 10:59:15 +02:00
2019-05-14 16:33:46 +02:00
s . Driver . Navigate ( ) . GoToUrl ( s . Link ( "/invoices" ) ) ;
Assert . Contains ( "ReturnUrl=%2Finvoices" , s . Driver . Url ) ;
// We should be redirected to login
2019-05-12 10:13:26 +02:00
//Same User Can Log Back In
2019-05-13 11:42:20 +02:00
s . Driver . FindElement ( By . Id ( "Email" ) ) . SendKeys ( email ) ;
s . Driver . FindElement ( By . Id ( "Password" ) ) . SendKeys ( "123456" ) ;
s . Driver . FindElement ( By . Id ( "LoginButton" ) ) . Click ( ) ;
2019-05-14 16:33:46 +02:00
// We should be redirected to invoice
Assert . EndsWith ( "/invoices" , s . Driver . Url ) ;
// Should not be able to reach server settings
s . Driver . Navigate ( ) . GoToUrl ( s . Link ( "/server/users" ) ) ;
Assert . Contains ( "ReturnUrl=%2Fserver%2Fusers" , s . Driver . Url ) ;
2019-05-12 10:13:26 +02:00
//Change Password & Log Out
2019-05-13 11:42:20 +02:00
s . Driver . FindElement ( By . Id ( "MySettings" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "ChangePassword" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "OldPassword" ) ) . SendKeys ( "123456" ) ;
s . Driver . FindElement ( By . Id ( "NewPassword" ) ) . SendKeys ( "abc???" ) ;
s . Driver . FindElement ( By . Id ( "ConfirmPassword" ) ) . SendKeys ( "abc???" ) ;
s . Driver . FindElement ( By . Id ( "UpdatePassword" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "Logout" ) ) . Click ( ) ;
s . Driver . AssertNoError ( ) ;
2019-05-12 10:13:26 +02:00
//Log In With New Password
2019-05-13 11:42:20 +02:00
s . Driver . FindElement ( By . Id ( "Login" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "Email" ) ) . SendKeys ( email ) ;
s . Driver . FindElement ( By . Id ( "Password" ) ) . SendKeys ( "abc???" ) ;
s . Driver . FindElement ( By . Id ( "LoginButton" ) ) . Click ( ) ;
Assert . True ( s . Driver . PageSource . Contains ( "Stores" ) , "Can't Access Stores" ) ;
2019-05-14 16:33:46 +02:00
s . Driver . FindElement ( By . Id ( "MySettings" ) ) . Click ( ) ;
s . ClickOnAllSideMenus ( ) ;
2019-05-13 11:42:20 +02:00
s . Driver . Quit ( ) ;
}
2019-05-12 10:13:26 +02:00
}
2019-05-14 16:33:46 +02:00
private static void LogIn ( SeleniumTester s , string email )
{
s . Driver . FindElement ( By . Id ( "Login" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "Email" ) ) . SendKeys ( email ) ;
s . Driver . FindElement ( By . Id ( "Password" ) ) . SendKeys ( "123456" ) ;
s . Driver . FindElement ( By . Id ( "LoginButton" ) ) . Click ( ) ;
s . Driver . AssertNoError ( ) ;
}
2019-05-12 10:13:26 +02:00
[Fact]
public void CanCreateStores ( )
{
2019-05-13 11:42:20 +02:00
using ( var s = SeleniumTester . Create ( ) )
2019-05-12 10:13:26 +02:00
{
2019-05-13 11:42:20 +02:00
s . Start ( ) ;
2019-05-14 16:33:46 +02:00
var alice = s . RegisterNewUser ( ) ;
2019-05-13 11:42:20 +02:00
var store = s . CreateNewStore ( ) ;
2019-05-14 16:33:46 +02:00
s . AddDerivationScheme ( ) ;
2019-05-13 11:42:20 +02:00
s . Driver . AssertNoError ( ) ;
Assert . Contains ( store , s . Driver . PageSource ) ;
2019-05-14 16:33:46 +02:00
var storeUrl = s . Driver . Url ;
2019-05-13 11:42:20 +02:00
s . ClickOnAllSideMenus ( ) ;
2019-05-13 10:59:15 +02:00
2019-05-14 16:33:46 +02:00
CreateInvoice ( s , store ) ;
s . Driver . FindElement ( By . ClassName ( "invoice-details-link" ) ) . Click ( ) ;
var invoiceUrl = s . Driver . Url ;
// When logout we should not be able to access store and invoice details
s . Driver . FindElement ( By . Id ( "Logout" ) ) . Click ( ) ;
s . Driver . Navigate ( ) . GoToUrl ( storeUrl ) ;
Assert . Contains ( "ReturnUrl" , s . Driver . Url ) ;
s . Driver . Navigate ( ) . GoToUrl ( invoiceUrl ) ;
Assert . Contains ( "ReturnUrl" , s . Driver . Url ) ;
// When logged we should not be able to access store and invoice details
var bob = s . RegisterNewUser ( ) ;
s . Driver . Navigate ( ) . GoToUrl ( storeUrl ) ;
Assert . Contains ( "ReturnUrl" , s . Driver . Url ) ;
s . Driver . Navigate ( ) . GoToUrl ( invoiceUrl ) ;
s . AssertNotFound ( ) ;
s . GoToHome ( ) ;
s . Logout ( ) ;
// Let's add Bob as a guest to alice's store
LogIn ( s , alice ) ;
s . Driver . Navigate ( ) . GoToUrl ( storeUrl + "/users" ) ;
s . Driver . FindElement ( By . Id ( "Email" ) ) . SendKeys ( bob + Keys . Enter ) ;
Assert . Contains ( "User added successfully" , s . Driver . PageSource ) ;
s . Logout ( ) ;
// Bob should not have access to store, but should have access to invoice
LogIn ( s , bob ) ;
s . Driver . Navigate ( ) . GoToUrl ( storeUrl ) ;
Assert . Contains ( "ReturnUrl" , s . Driver . Url ) ;
s . Driver . Navigate ( ) . GoToUrl ( invoiceUrl ) ;
s . Driver . AssertNoError ( ) ;
2019-05-13 10:59:15 +02:00
}
}
2019-05-12 10:13:26 +02:00
[Fact]
public void CanCreateInvoice ( )
{
2019-05-13 11:42:20 +02:00
using ( var s = SeleniumTester . Create ( ) )
2019-05-12 10:13:26 +02:00
{
2019-05-13 11:42:20 +02:00
s . Start ( ) ;
s . RegisterNewUser ( ) ;
var store = s . CreateNewStore ( ) ;
s . AddDerivationScheme ( ) ;
2019-05-14 16:33:46 +02:00
CreateInvoice ( s , store ) ;
s . Driver . FindElement ( By . ClassName ( "invoice-details-link" ) ) . Click ( ) ;
s . Driver . AssertNoError ( ) ;
s . Driver . Navigate ( ) . Back ( ) ;
s . Driver . FindElement ( By . ClassName ( "invoice-checkout-link" ) ) . Click ( ) ;
Assert . NotEmpty ( s . Driver . FindElements ( By . Id ( "checkoutCtrl" ) ) ) ;
2019-05-13 11:42:20 +02:00
s . Driver . Quit ( ) ;
}
2019-05-12 10:13:26 +02:00
}
2019-05-14 16:33:46 +02:00
private static void CreateInvoice ( SeleniumTester s , string store )
{
s . Driver . FindElement ( By . Id ( "Invoices" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "CreateNewInvoice" ) ) . Click ( ) ;
s . Driver . FindElement ( By . CssSelector ( "input#Amount.form-control" ) ) . SendKeys ( "100" ) ;
s . Driver . FindElement ( By . Name ( "StoreId" ) ) . SendKeys ( store + Keys . Enter ) ;
s . Driver . FindElement ( By . Id ( "Create" ) ) . Click ( ) ;
Assert . True ( s . Driver . PageSource . Contains ( "just created!" ) , "Unable to create Invoice" ) ;
}
2019-05-12 10:13:26 +02:00
[Fact]
public void CanCreateAppPoS ( )
{
2019-05-13 11:42:20 +02:00
using ( var s = SeleniumTester . Create ( ) )
2019-05-12 10:13:26 +02:00
{
2019-05-13 11:42:20 +02:00
s . Start ( ) ;
s . RegisterNewUser ( ) ;
var store = s . CreateNewStore ( ) ;
s . Driver . FindElement ( By . Id ( "Apps" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "CreateNewApp" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Name ( "Name" ) ) . SendKeys ( "PoS" + store ) ;
s . Driver . FindElement ( By . CssSelector ( "select#SelectedAppType.form-control" ) ) . SendKeys ( "PointOfSale" + Keys . Enter ) ;
s . Driver . FindElement ( By . CssSelector ( "select#SelectedStore.form-control" ) ) . SendKeys ( store + Keys . Enter ) ;
s . Driver . FindElement ( By . Id ( "Create" ) ) . Click ( ) ;
s . Driver . FindElement ( By . CssSelector ( "input#EnableShoppingCart.form-check" ) ) . Click ( ) ;
2019-05-14 15:29:05 +02:00
s . Driver . FindElement ( By . Id ( "SaveSettings" ) ) . ForceClick ( ) ;
2019-05-13 11:42:20 +02:00
Assert . True ( s . Driver . PageSource . Contains ( "App updated" ) , "Unable to create PoS" ) ;
s . Driver . Quit ( ) ;
}
2019-05-12 10:13:26 +02:00
}
[Fact]
public void CanCreateAppCF ( )
{
2019-05-13 11:42:20 +02:00
using ( var s = SeleniumTester . Create ( ) )
2019-05-12 10:13:26 +02:00
{
2019-05-13 11:42:20 +02:00
s . Start ( ) ;
s . RegisterNewUser ( ) ;
var store = s . CreateNewStore ( ) ;
s . AddDerivationScheme ( ) ;
s . Driver . FindElement ( By . Id ( "Apps" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "CreateNewApp" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Name ( "Name" ) ) . SendKeys ( "CF" + store ) ;
s . Driver . FindElement ( By . CssSelector ( "select#SelectedAppType.form-control" ) ) . SendKeys ( "Crowdfund" + Keys . Enter ) ;
s . Driver . FindElement ( By . CssSelector ( "select#SelectedStore.form-control" ) ) . SendKeys ( store + Keys . Enter ) ;
s . Driver . FindElement ( By . Id ( "Create" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "Title" ) ) . SendKeys ( "Kukkstarter" ) ;
s . Driver . FindElement ( By . CssSelector ( "div.note-editable.card-block" ) ) . SendKeys ( "1BTC = 1BTC" ) ;
s . Driver . FindElement ( By . Id ( "TargetCurrency" ) ) . SendKeys ( "JPY" ) ;
s . Driver . FindElement ( By . Id ( "TargetAmount" ) ) . SendKeys ( "700" ) ;
s . Driver . FindElement ( By . Id ( "SaveSettings" ) ) . Submit ( ) ;
2019-05-14 15:29:05 +02:00
s . Driver . FindElement ( By . Id ( "ViewApp" ) ) . ForceClick ( ) ;
2019-05-13 11:42:20 +02:00
s . Driver . SwitchTo ( ) . Window ( s . Driver . WindowHandles . Last ( ) ) ;
Assert . True ( s . Driver . PageSource . Contains ( "Currently Active!" ) , "Unable to create CF" ) ;
s . Driver . Quit ( ) ;
}
2019-05-12 10:13:26 +02:00
}
[Fact]
public void CanCreatePayRequest ( )
{
2019-05-13 11:42:20 +02:00
using ( var s = SeleniumTester . Create ( ) )
2019-05-12 10:13:26 +02:00
{
2019-05-13 11:42:20 +02:00
s . Start ( ) ;
s . RegisterNewUser ( ) ;
s . CreateNewStore ( ) ;
s . AddDerivationScheme ( ) ;
s . Driver . FindElement ( By . Id ( "PaymentRequests" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "CreatePaymentRequest" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "Title" ) ) . SendKeys ( "Pay123" ) ;
s . Driver . FindElement ( By . Id ( "Amount" ) ) . SendKeys ( "700" ) ;
s . Driver . FindElement ( By . Id ( "Currency" ) ) . SendKeys ( "BTC" ) ;
s . Driver . FindElement ( By . Id ( "SaveButton" ) ) . Submit ( ) ;
s . Driver . FindElement ( By . Name ( "ViewAppButton" ) ) . SendKeys ( Keys . Return ) ;
s . Driver . SwitchTo ( ) . Window ( s . Driver . WindowHandles . Last ( ) ) ;
Assert . True ( s . Driver . PageSource . Contains ( "Amount due" ) , "Unable to create Payment Request" ) ;
s . Driver . Quit ( ) ;
}
2019-05-12 10:13:26 +02:00
}
2019-05-13 10:59:15 +02:00
[Fact]
public void CanManageWallet ( )
{
2019-05-13 11:42:20 +02:00
using ( var s = SeleniumTester . Create ( ) )
2019-05-13 10:59:15 +02:00
{
2019-05-13 11:42:20 +02:00
s . Start ( ) ;
s . RegisterNewUser ( ) ;
s . CreateNewStore ( ) ;
2019-05-15 09:00:03 +02:00
// In this test, we try to spend from a manual seed. We import the xpub 49'/0'/0', then try to use the seed
// to sign the transaction
var mnemonic = "usage fever hen zero slide mammal silent heavy donate budget pulse say brain thank sausage brand craft about save attract muffin advance illegal cabbage" ;
var root = new Mnemonic ( mnemonic ) . DeriveExtKey ( ) ;
s . AddDerivationScheme ( "ypub6WWc2gWwHbdnAAyJDnR4SPL1phRh7REqrPBfZeizaQ1EmTshieRXJC3Z5YoU4wkcdKHEjQGkh6AYEzCQC1Kz3DNaWSwdc1pc8416hAjzqyD" ) ;
2019-05-15 12:00:26 +02:00
var tx = s . Server . ExplorerNode . SendToAddress ( BitcoinAddress . Create ( "bcrt1qmxg8fgnmkp354vhe78j6sr4ut64tyz2xyejel4" , Network . RegTest ) , Money . Coins ( 3.0 m ) ) ;
s . Server . ExplorerNode . Generate ( 1 ) ;
2019-05-13 10:59:15 +02:00
2019-05-13 11:42:20 +02:00
s . Driver . FindElement ( By . Id ( "Wallets" ) ) . Click ( ) ;
s . Driver . FindElement ( By . LinkText ( "Manage" ) ) . Click ( ) ;
2019-05-13 10:59:15 +02:00
2019-05-13 11:42:20 +02:00
s . ClickOnAllSideMenus ( ) ;
2019-05-13 10:59:15 +02:00
2019-05-15 09:00:03 +02:00
// We setup the fingerprint and the account key path
s . Driver . FindElement ( By . Id ( "WalletSettings" ) ) . ForceClick ( ) ;
s . Driver . FindElement ( By . Id ( "AccountKeys_0__MasterFingerprint" ) ) . SendKeys ( "8bafd160" ) ;
s . Driver . FindElement ( By . Id ( "AccountKeys_0__AccountKeyPath" ) ) . SendKeys ( "m/49'/0'/0'" + Keys . Enter ) ;
// Check the tx sent earlier arrived
s . Driver . FindElement ( By . Id ( "WalletTransactions" ) ) . ForceClick ( ) ;
var walletTransactionLink = s . Driver . Url ;
Assert . Contains ( tx . ToString ( ) , s . Driver . PageSource ) ;
2019-05-15 12:00:26 +02:00
void SignWith ( string signingSource )
{
// Send to bob
s . Driver . FindElement ( By . Id ( "WalletSend" ) ) . Click ( ) ;
var bob = new Key ( ) . PubKey . Hash . GetAddress ( Network . RegTest ) ;
s . Driver . FindElement ( By . Id ( "Destination" ) ) . SendKeys ( bob . ToString ( ) ) ;
s . Driver . FindElement ( By . Id ( "Amount" ) ) . SendKeys ( "1" ) ;
2019-05-15 12:27:30 +02:00
s . Driver . ScrollTo ( By . Id ( "SendMenu" ) ) ;
s . Driver . FindElement ( By . Id ( "SendMenu" ) ) . ForceClick ( ) ;
2019-05-15 12:00:26 +02:00
s . Driver . FindElement ( By . CssSelector ( "button[value=seed]" ) ) . Click ( ) ;
// Input the seed
s . Driver . FindElement ( By . Id ( "SeedOrKey" ) ) . SendKeys ( signingSource + Keys . Enter ) ;
// Broadcast
Assert . Contains ( bob . ToString ( ) , s . Driver . PageSource ) ;
Assert . Contains ( "1.00000000" , s . Driver . PageSource ) ;
s . Driver . FindElement ( By . CssSelector ( "button[value=broadcast]" ) ) . Click ( ) ;
Assert . Equal ( walletTransactionLink , s . Driver . Url ) ;
}
SignWith ( mnemonic ) ;
var accountKey = root . Derive ( new KeyPath ( "m/49'/0'/0'" ) ) . GetWif ( Network . RegTest ) . ToString ( ) ;
SignWith ( accountKey ) ;
2019-05-13 11:42:20 +02:00
}
2019-05-12 10:13:26 +02:00
}
}
}