2020-06-29 04:44:35 +02:00
using System ;
2021-04-13 10:36:49 +02:00
using System.Collections.ObjectModel ;
2020-06-28 10:55:27 +02:00
using System.Globalization ;
2019-05-12 10:13:26 +02:00
using System.Linq ;
2021-10-26 13:55:13 +02:00
using System.Net.Http ;
2020-11-06 12:42:26 +01:00
using System.Text ;
2019-10-12 13:35:30 +02:00
using System.Text.RegularExpressions ;
2021-10-18 05:37:59 +02:00
using System.Threading ;
2020-06-28 10:55:27 +02:00
using System.Threading.Tasks ;
2020-11-17 13:46:23 +01:00
using BTCPayServer.Abstractions.Models ;
2020-11-06 12:42:26 +01:00
using BTCPayServer.Client.Models ;
2020-03-25 07:59:30 +01:00
using BTCPayServer.Data ;
2021-10-18 05:37:59 +02:00
using BTCPayServer.Lightning ;
2021-10-26 13:55:13 +02:00
using BTCPayServer.Lightning.CLightning ;
2021-10-18 05:37:59 +02:00
using BTCPayServer.Payments ;
2021-04-17 06:29:50 +02:00
using BTCPayServer.Services ;
2021-10-26 13:55:13 +02:00
using BTCPayServer.Services.Invoices ;
2020-03-25 07:59:30 +01:00
using BTCPayServer.Services.Wallets ;
2021-12-24 09:27:00 +01:00
using BTCPayServer.Views.Manage ;
2020-09-16 08:54:09 +02:00
using BTCPayServer.Views.Server ;
2021-04-07 06:08:42 +02:00
using BTCPayServer.Views.Stores ;
2020-04-28 08:06:28 +02:00
using BTCPayServer.Views.Wallets ;
2021-10-26 13:55:13 +02:00
using LNURL ;
2021-02-12 04:21:29 +01:00
using Microsoft.AspNetCore.Identity ;
2020-06-24 03:34:09 +02:00
using Microsoft.EntityFrameworkCore ;
2020-06-28 10:55:27 +02:00
using NBitcoin ;
2020-11-06 12:42:26 +01:00
using NBitcoin.DataEncoders ;
2020-06-28 10:55:27 +02:00
using NBitcoin.Payment ;
2020-11-06 12:42:26 +01:00
using Newtonsoft.Json.Linq ;
2020-06-28 10:55:27 +02:00
using OpenQA.Selenium ;
2020-11-06 12:42:26 +01:00
using OpenQA.Selenium.Support.Extensions ;
using OpenQA.Selenium.Support.UI ;
using Renci.SshNet.Security.Cryptography ;
2020-06-28 10:55:27 +02:00
using Xunit ;
using Xunit.Abstractions ;
2019-05-12 10:13:26 +02:00
namespace BTCPayServer.Tests
{
2019-05-13 11:42:20 +02:00
[Trait("Selenium", "Selenium")]
2021-11-23 05:57:45 +01:00
[Collection(nameof(NonParallelizableCollectionDefinition))]
2021-11-22 09:16:08 +01:00
public class ChromeTests : UnitTestBase
2019-05-12 10:13:26 +02:00
{
2021-01-22 17:49:26 +01:00
private const int TestTimeout = TestUtils . TestTimeout ;
2021-11-22 09:16:08 +01:00
public ChromeTests ( ITestOutputHelper helper ) : base ( helper )
2019-05-12 10:13:26 +02:00
{
}
2019-10-06 15:24:28 +02:00
[Fact(Timeout = TestTimeout)]
2019-10-07 09:04:25 +02:00
public async Task CanNavigateServerSettings ( )
2019-05-13 10:59:15 +02:00
{
2022-01-14 09:50:29 +01:00
using var s = CreateSeleniumTester ( ) ;
await s . StartAsync ( ) ;
s . RegisterNewUser ( true ) ;
s . Driver . FindElement ( By . Id ( "Nav-ServerSettings" ) ) . Click ( ) ;
s . Driver . AssertNoError ( ) ;
s . ClickOnAllSectionLinks ( ) ;
2022-01-28 14:51:12 +01:00
s . Driver . FindElement ( By . Id ( "Nav-ServerSettings" ) ) . Click ( ) ;
2022-01-14 09:50:29 +01:00
s . Driver . FindElement ( By . LinkText ( "Services" ) ) . Click ( ) ;
TestLogs . LogInformation ( "Let's check if we can access the logs" ) ;
s . Driver . FindElement ( By . LinkText ( "Logs" ) ) . Click ( ) ;
s . Driver . FindElement ( By . PartialLinkText ( ".log" ) ) . Click ( ) ;
Assert . Contains ( "Starting listening NBXplorer" , s . Driver . PageSource ) ;
s . Driver . Quit ( ) ;
2019-12-24 10:11:21 +01:00
}
[Fact(Timeout = TestTimeout)]
[Trait("Lightning", "Lightning")]
public async Task CanUseLndSeedBackup ( )
{
2022-01-14 09:50:29 +01:00
using var s = CreateSeleniumTester ( ) ;
s . Server . ActivateLightning ( ) ;
await s . StartAsync ( ) ;
s . RegisterNewUser ( true ) ;
s . Driver . FindElement ( By . Id ( "Nav-ServerSettings" ) ) . Click ( ) ;
s . Driver . AssertNoError ( ) ;
s . Driver . FindElement ( By . LinkText ( "Services" ) ) . Click ( ) ;
TestLogs . LogInformation ( "Let's if we can access LND's seed" ) ;
Assert . Contains ( "server/services/lndseedbackup/BTC" , s . Driver . PageSource ) ;
s . Driver . Navigate ( ) . GoToUrl ( s . Link ( "/server/services/lndseedbackup/BTC" ) ) ;
s . Driver . FindElement ( By . Id ( "details" ) ) . Click ( ) ;
var seedEl = s . Driver . FindElement ( By . Id ( "Seed" ) ) ;
Assert . True ( seedEl . Displayed ) ;
Assert . Contains ( "about over million" , seedEl . Text , StringComparison . OrdinalIgnoreCase ) ;
var passEl = s . Driver . FindElement ( By . Id ( "WalletPassword" ) ) ;
Assert . True ( passEl . Displayed ) ;
Assert . Contains ( passEl . Text , "hellorockstar" , StringComparison . OrdinalIgnoreCase ) ;
s . Driver . FindElement ( By . Id ( "delete" ) ) . Click ( ) ;
s . Driver . WaitForElement ( By . Id ( "ConfirmInput" ) ) . SendKeys ( "DELETE" ) ;
s . Driver . FindElement ( By . Id ( "ConfirmContinue" ) ) . Click ( ) ;
s . FindAlertMessage ( ) ;
seedEl = s . Driver . FindElement ( By . Id ( "Seed" ) ) ;
Assert . Contains ( "Seed removed" , seedEl . Text , StringComparison . OrdinalIgnoreCase ) ;
2019-05-13 10:59:15 +02:00
}
2021-02-12 04:21:29 +01:00
[Fact(Timeout = TestTimeout)]
[Trait("Selenium", "Selenium")]
public async Task CanChangeUserMail ( )
{
2022-01-14 09:50:29 +01:00
using var s = CreateSeleniumTester ( ) ;
await s . StartAsync ( ) ;
2021-02-12 04:21:29 +01:00
2022-01-14 09:50:29 +01:00
var tester = s . Server ;
var u1 = tester . NewAccount ( ) ;
await u1 . GrantAccessAsync ( ) ;
await u1 . MakeAdmin ( false ) ;
var u2 = tester . NewAccount ( ) ;
await u2 . GrantAccessAsync ( ) ;
await u2 . MakeAdmin ( false ) ;
s . GoToLogin ( ) ;
s . Login ( u1 . RegisterDetails . Email , u1 . RegisterDetails . Password ) ;
s . GoToProfile ( ) ;
s . Driver . FindElement ( By . Id ( "Email" ) ) . Clear ( ) ;
s . Driver . FindElement ( By . Id ( "Email" ) ) . SendKeys ( u2 . RegisterDetails . Email ) ;
s . Driver . FindElement ( By . Id ( "save" ) ) . Click ( ) ;
Assert . Contains ( "The email address is already in use with an other account." ,
s . FindAlertMessage ( StatusMessageModel . StatusSeverity . Error ) . Text ) ;
s . GoToProfile ( ) ;
s . Driver . FindElement ( By . Id ( "Email" ) ) . Clear ( ) ;
var changedEmail = Guid . NewGuid ( ) + "@lol.com" ;
s . Driver . FindElement ( By . Id ( "Email" ) ) . SendKeys ( changedEmail ) ;
s . Driver . FindElement ( By . Id ( "save" ) ) . Click ( ) ;
s . FindAlertMessage ( ) ;
var manager = tester . PayTester . GetService < UserManager < ApplicationUser > > ( ) ;
Assert . NotNull ( await manager . FindByNameAsync ( changedEmail ) ) ;
Assert . NotNull ( await manager . FindByEmailAsync ( changedEmail ) ) ;
2021-02-12 04:21:29 +01:00
}
2019-10-06 15:24:28 +02:00
[Fact(Timeout = TestTimeout)]
2019-10-07 09:04:25 +02:00
public async Task NewUserLogin ( )
2019-05-12 10:13:26 +02:00
{
2022-01-14 09:50:29 +01:00
using var s = CreateSeleniumTester ( ) ;
await s . StartAsync ( ) ;
//Register & Log Out
var email = s . RegisterNewUser ( ) ;
s . Logout ( ) ;
s . Driver . AssertNoError ( ) ;
Assert . Contains ( "/login" , s . Driver . Url ) ;
2022-01-14 12:16:28 +01:00
s . GoToUrl ( "/account" ) ;
Assert . Contains ( "ReturnUrl=%2Faccount" , s . Driver . Url ) ;
2022-01-14 09:50:29 +01:00
// We should be redirected to login
//Same User Can Log Back In
s . Driver . FindElement ( By . Id ( "Email" ) ) . SendKeys ( email ) ;
s . Driver . FindElement ( By . Id ( "Password" ) ) . SendKeys ( "123456" ) ;
s . Driver . FindElement ( By . Id ( "LoginButton" ) ) . Click ( ) ;
// We should be redirected to invoice
2022-01-14 12:16:28 +01:00
Assert . EndsWith ( "/account" , s . Driver . Url ) ;
2022-01-14 09:50:29 +01:00
// Should not be able to reach server settings
s . GoToUrl ( "/server/users" ) ;
Assert . Contains ( "ReturnUrl=%2Fserver%2Fusers" , s . Driver . Url ) ;
s . GoToHome ( ) ;
//Change Password & Log Out
s . GoToProfile ( ManageNavPages . ChangePassword ) ;
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 . Logout ( ) ;
s . Driver . AssertNoError ( ) ;
//Log In With New Password
s . Driver . FindElement ( By . Id ( "Email" ) ) . SendKeys ( email ) ;
s . Driver . FindElement ( By . Id ( "Password" ) ) . SendKeys ( "abc???" ) ;
s . Driver . FindElement ( By . Id ( "LoginButton" ) ) . Click ( ) ;
s . GoToProfile ( ) ;
s . ClickOnAllSectionLinks ( ) ;
//let's test invite link
s . Logout ( ) ;
s . GoToRegister ( ) ;
s . RegisterNewUser ( true ) ;
s . GoToServer ( ServerNavPages . Users ) ;
s . Driver . FindElement ( By . Id ( "CreateUser" ) ) . Click ( ) ;
var usr = RandomUtils . GetUInt256 ( ) . ToString ( ) . Substring ( 64 - 20 ) + "@a.com" ;
s . Driver . FindElement ( By . Id ( "Email" ) ) . SendKeys ( usr ) ;
s . Driver . FindElement ( By . Id ( "Save" ) ) . Click ( ) ;
var url = s . FindAlertMessage ( ) . FindElement ( By . TagName ( "a" ) ) . Text ;
s . Logout ( ) ;
s . Driver . Navigate ( ) . GoToUrl ( url ) ;
Assert . Equal ( "hidden" , s . Driver . FindElement ( By . Id ( "Email" ) ) . GetAttribute ( "type" ) ) ;
Assert . Equal ( usr , s . Driver . FindElement ( By . Id ( "Email" ) ) . GetAttribute ( "value" ) ) ;
s . Driver . FindElement ( By . Id ( "Password" ) ) . SendKeys ( "123456" ) ;
s . Driver . FindElement ( By . Id ( "ConfirmPassword" ) ) . SendKeys ( "123456" ) ;
s . Driver . FindElement ( By . Id ( "SetPassword" ) ) . Click ( ) ;
s . FindAlertMessage ( ) ;
s . Driver . FindElement ( By . Id ( "Email" ) ) . SendKeys ( usr ) ;
s . Driver . FindElement ( By . Id ( "Password" ) ) . SendKeys ( "123456" ) ;
s . Driver . FindElement ( By . Id ( "LoginButton" ) ) . Click ( ) ;
// We should be logged in now
s . Driver . FindElement ( By . Id ( "mainNav" ) ) ;
//let's test delete user quickly while we're at it
s . GoToProfile ( ) ;
s . Driver . FindElement ( By . Id ( "delete-user" ) ) . Click ( ) ;
s . Driver . WaitForElement ( By . Id ( "ConfirmInput" ) ) . SendKeys ( "DELETE" ) ;
s . Driver . FindElement ( By . Id ( "ConfirmContinue" ) ) . Click ( ) ;
Assert . Contains ( "/login" , s . Driver . Url ) ;
2019-05-12 10:13:26 +02:00
}
2019-05-14 16:33:46 +02:00
2019-10-06 15:24:28 +02:00
[Fact(Timeout = TestTimeout)]
2019-09-06 09:51:49 +02:00
public async Task CanUseSSHService ( )
{
2022-01-14 09:50:29 +01:00
using var s = CreateSeleniumTester ( ) ;
await s . StartAsync ( ) ;
var settings = s . Server . PayTester . GetService < SettingsRepository > ( ) ;
var policies = await settings . GetSettingAsync < PoliciesSettings > ( ) ? ? new PoliciesSettings ( ) ;
policies . DisableSSHService = false ;
await settings . UpdateSetting ( policies ) ;
s . RegisterNewUser ( isAdmin : true ) ;
s . Driver . Navigate ( ) . GoToUrl ( s . Link ( "/server/services" ) ) ;
Assert . Contains ( "server/services/ssh" , s . Driver . PageSource ) ;
using ( var client = await s . Server . PayTester . GetService < Configuration . BTCPayServerOptions > ( ) . SSHSettings
. ConnectAsync ( ) )
2019-09-06 09:51:49 +02:00
{
2022-01-14 09:50:29 +01:00
var result = await client . RunBash ( "echo hello" ) ;
Assert . Equal ( string . Empty , result . Error ) ;
Assert . Equal ( "hello\n" , result . Output ) ;
Assert . Equal ( 0 , result . ExitStatus ) ;
2019-09-06 09:51:49 +02:00
}
2022-01-14 09:50:29 +01:00
s . Driver . Navigate ( ) . GoToUrl ( s . Link ( "/server/services/ssh" ) ) ;
s . Driver . AssertNoError ( ) ;
s . Driver . FindElement ( By . Id ( "SSHKeyFileContent" ) ) . Clear ( ) ;
s . Driver . FindElement ( By . Id ( "SSHKeyFileContent" ) ) . SendKeys ( "tes't\r\ntest2" ) ;
s . Driver . FindElement ( By . Id ( "submit" ) ) . Click ( ) ;
s . Driver . AssertNoError ( ) ;
var text = s . Driver . FindElement ( By . Id ( "SSHKeyFileContent" ) ) . Text ;
// Browser replace \n to \r\n, so it is hard to compare exactly what we want
Assert . Contains ( "tes't" , text ) ;
Assert . Contains ( "test2" , text ) ;
Assert . True ( s . Driver . PageSource . Contains ( "authorized_keys has been updated" ,
StringComparison . OrdinalIgnoreCase ) ) ;
s . Driver . FindElement ( By . Id ( "SSHKeyFileContent" ) ) . Clear ( ) ;
s . Driver . FindElement ( By . Id ( "submit" ) ) . Click ( ) ;
text = s . Driver . FindElement ( By . Id ( "SSHKeyFileContent" ) ) . Text ;
Assert . DoesNotContain ( "test2" , text ) ;
// Let's try to disable it now
s . Driver . FindElement ( By . Id ( "disable" ) ) . Click ( ) ;
s . Driver . WaitForElement ( By . Id ( "ConfirmInput" ) ) . SendKeys ( "DISABLE" ) ;
s . Driver . FindElement ( By . Id ( "ConfirmContinue" ) ) . Click ( ) ;
s . Driver . Navigate ( ) . GoToUrl ( s . Link ( "/server/services/ssh" ) ) ;
Assert . True ( s . Driver . PageSource . Contains ( "404 - Page not found" , StringComparison . OrdinalIgnoreCase ) ) ;
policies = await settings . GetSettingAsync < PoliciesSettings > ( ) ;
Assert . True ( policies . DisableSSHService ) ;
policies . DisableSSHService = false ;
await settings . UpdateSetting ( policies ) ;
2019-09-06 09:51:49 +02:00
}
2020-10-05 09:39:49 +02:00
[Fact(Timeout = TestTimeout)]
public async Task CanSetupEmailServer ( )
{
2022-01-14 09:50:29 +01:00
using var s = CreateSeleniumTester ( ) ;
await s . StartAsync ( ) ;
2022-01-18 02:19:27 +01:00
s . RegisterNewUser ( true ) ;
2022-01-14 09:50:29 +01:00
s . Driver . Navigate ( ) . GoToUrl ( s . Link ( "/server/emails" ) ) ;
if ( s . Driver . PageSource . Contains ( "Configured" ) )
2020-10-05 09:39:49 +02:00
{
2022-01-18 02:19:27 +01:00
s . Driver . FindElement ( By . Id ( "ResetPassword" ) ) . Submit ( ) ;
2022-01-14 09:50:29 +01:00
s . FindAlertMessage ( ) ;
2020-10-05 09:39:49 +02:00
}
2022-01-14 09:50:29 +01:00
CanSetupEmailCore ( s ) ;
s . CreateNewStore ( ) ;
s . GoToUrl ( $"stores/{s.StoreId}/emails" ) ;
CanSetupEmailCore ( s ) ;
2020-10-05 09:39:49 +02:00
}
2019-10-06 15:24:28 +02:00
[Fact(Timeout = TestTimeout)]
2019-10-07 09:04:25 +02:00
public async Task CanUseDynamicDns ( )
2019-07-25 12:07:56 +02:00
{
2022-01-14 09:50:29 +01:00
using var s = CreateSeleniumTester ( ) ;
await s . StartAsync ( ) ;
s . RegisterNewUser ( isAdmin : true ) ;
s . Driver . Navigate ( ) . GoToUrl ( s . Link ( "/server/services" ) ) ;
Assert . Contains ( "Dynamic DNS" , s . Driver . PageSource ) ;
s . Driver . Navigate ( ) . GoToUrl ( s . Link ( "/server/services/dynamic-dns" ) ) ;
s . Driver . AssertNoError ( ) ;
if ( s . Driver . PageSource . Contains ( "pouet.hello.com" ) )
2019-07-25 12:07:56 +02:00
{
2022-01-14 09:50:29 +01:00
// Cleanup old test run
2019-09-11 09:22:41 +02:00
s . Driver . Navigate ( ) . GoToUrl ( s . Link ( "/server/services/dynamic-dns/pouet.hello.com/delete" ) ) ;
2021-09-07 04:55:53 +02:00
s . Driver . FindElement ( By . Id ( "ConfirmContinue" ) ) . Click ( ) ;
2019-07-25 12:07:56 +02:00
}
2022-01-14 09:50:29 +01:00
s . Driver . FindElement ( By . Id ( "AddDynamicDNS" ) ) . Click ( ) ;
s . Driver . AssertNoError ( ) ;
// We will just cheat for test purposes by only querying the server
s . Driver . FindElement ( By . Id ( "ServiceUrl" ) ) . SendKeys ( s . Link ( "/" ) ) ;
s . Driver . FindElement ( By . Id ( "Settings_Hostname" ) ) . SendKeys ( "pouet.hello.com" ) ;
s . Driver . FindElement ( By . Id ( "Settings_Login" ) ) . SendKeys ( "MyLog" ) ;
s . Driver . FindElement ( By . Id ( "Settings_Password" ) ) . SendKeys ( "MyLog" + Keys . Enter ) ;
s . Driver . AssertNoError ( ) ;
Assert . Contains ( "The Dynamic DNS has been successfully queried" , s . Driver . PageSource ) ;
Assert . EndsWith ( "/server/services/dynamic-dns" , s . Driver . Url ) ;
// Try to do the same thing should fail (hostname already exists)
s . Driver . FindElement ( By . Id ( "AddDynamicDNS" ) ) . Click ( ) ;
s . Driver . AssertNoError ( ) ;
s . Driver . FindElement ( By . Id ( "ServiceUrl" ) ) . SendKeys ( s . Link ( "/" ) ) ;
s . Driver . FindElement ( By . Id ( "Settings_Hostname" ) ) . SendKeys ( "pouet.hello.com" ) ;
s . Driver . FindElement ( By . Id ( "Settings_Login" ) ) . SendKeys ( "MyLog" ) ;
s . Driver . FindElement ( By . Id ( "Settings_Password" ) ) . SendKeys ( "MyLog" + Keys . Enter ) ;
s . Driver . AssertNoError ( ) ;
Assert . Contains ( "This hostname already exists" , s . Driver . PageSource ) ;
// Delete it
s . Driver . Navigate ( ) . GoToUrl ( s . Link ( "/server/services/dynamic-dns" ) ) ;
Assert . Contains ( "/server/services/dynamic-dns/pouet.hello.com/delete" , s . Driver . PageSource ) ;
s . Driver . Navigate ( ) . GoToUrl ( s . Link ( "/server/services/dynamic-dns/pouet.hello.com/delete" ) ) ;
s . Driver . FindElement ( By . Id ( "ConfirmContinue" ) ) . Click ( ) ;
s . Driver . AssertNoError ( ) ;
Assert . DoesNotContain ( "/server/services/dynamic-dns/pouet.hello.com/delete" , s . Driver . PageSource ) ;
2019-07-25 12:07:56 +02:00
}
2022-01-19 12:58:02 +01:00
2022-01-11 13:49:56 +01:00
[Fact(Timeout = TestTimeout)]
public async Task CanCreateInvoiceInUI ( )
{
using var s = CreateSeleniumTester ( ) ;
await s . StartAsync ( ) ;
s . RegisterNewUser ( true ) ;
s . CreateNewStore ( ) ;
s . AddDerivationScheme ( ) ;
s . GoToInvoices ( ) ;
s . CreateInvoice ( ) ;
s . Driver . FindElement ( By . ClassName ( "changeInvoiceStateToggle" ) ) . Click ( ) ;
s . Driver . FindElements ( By . ClassName ( "changeInvoiceState" ) ) [ 0 ] . Click ( ) ;
TestUtils . Eventually ( ( ) = > Assert . Contains ( "Invalid (marked)" , s . Driver . PageSource ) ) ;
s . Driver . Navigate ( ) . Refresh ( ) ;
s . Driver . FindElement ( By . ClassName ( "changeInvoiceStateToggle" ) ) . Click ( ) ;
s . Driver . FindElements ( By . ClassName ( "changeInvoiceState" ) ) [ 0 ] . Click ( ) ;
TestUtils . Eventually ( ( ) = > Assert . Contains ( "Settled (marked)" , s . Driver . PageSource ) ) ;
s . Driver . FindElement ( By . ClassName ( "invoice-details-link" ) ) . Click ( ) ;
Assert . Contains ( "Settled (marked)" , s . Driver . PageSource ) ;
s . Driver . FindElement ( By . ClassName ( "changeInvoiceStateToggle" ) ) . Click ( ) ;
s . Driver . FindElements ( By . ClassName ( "changeInvoiceState" ) ) [ 0 ] . Click ( ) ;
TestUtils . Eventually ( ( ) = > Assert . Contains ( "Invalid (marked)" , s . Driver . PageSource ) ) ;
s . Driver . Navigate ( ) . Refresh ( ) ;
s . Driver . FindElement ( By . ClassName ( "changeInvoiceStateToggle" ) ) . Click ( ) ;
s . Driver . FindElements ( By . ClassName ( "changeInvoiceState" ) ) [ 0 ] . Click ( ) ;
TestUtils . Eventually ( ( ) = > Assert . Contains ( "Settled (marked)" , s . Driver . PageSource ) ) ;
}
2019-05-12 10:13:26 +02:00
2022-01-13 09:08:15 +01:00
[Fact(Timeout = TestTimeout)]
public async Task CanSetupStoreViaGuide ( )
{
2022-01-14 09:50:29 +01:00
using var s = CreateSeleniumTester ( ) ;
await s . StartAsync ( ) ;
s . RegisterNewUser ( ) ;
s . GoToUrl ( "/" ) ;
Assert . False ( s . Driver . PageSource . Contains ( "id=\"StoreSelectorDropdown\"" ) , "Store selector dropdown should not be present" ) ;
Assert . True ( s . Driver . PageSource . Contains ( "id=\"StoreSelectorCreate\"" ) , "Store selector create button should be present" ) ;
// verify steps for store creation are displayed correctly
s . Driver . FindElement ( By . Id ( "SetupGuide-Store" ) ) . Click ( ) ;
Assert . Contains ( "/stores/create" , s . Driver . Url ) ;
2022-01-18 02:20:59 +01:00
( _ , string storeId ) = s . CreateNewStore ( ) ;
// should redirect to store
2022-01-14 09:50:29 +01:00
s . GoToUrl ( "/" ) ;
2022-01-18 02:20:59 +01:00
Assert . Contains ( $"/stores/{storeId}" , s . Driver . Url ) ;
2022-01-14 09:50:29 +01:00
Assert . True ( s . Driver . PageSource . Contains ( "id=\"StoreSelectorDropdown\"" ) , "Store selector dropdown should be present" ) ;
2022-01-18 02:20:59 +01:00
Assert . True ( s . Driver . PageSource . Contains ( "id=\"SetupGuide\"" ) , "Store setup guide should be present" ) ;
2022-01-13 09:08:15 +01:00
}
2019-10-06 15:24:28 +02:00
[Fact(Timeout = TestTimeout)]
2021-03-31 13:23:36 +02:00
[Trait("Lightning", "Lightning")]
2019-10-07 09:04:25 +02:00
public async Task CanCreateStores ( )
2019-05-12 10:13:26 +02:00
{
2022-01-14 09:50:29 +01:00
using var s = CreateSeleniumTester ( ) ;
s . Server . ActivateLightning ( ) ;
await s . StartAsync ( ) ;
var alice = s . RegisterNewUser ( true ) ;
( string storeName , string storeId ) = s . CreateNewStore ( ) ;
var storeUrl = $"/stores/{storeId}" ;
2022-01-20 12:52:31 +01:00
s . GoToStore ( ) ;
2022-01-14 09:50:29 +01:00
Assert . Contains ( storeName , s . Driver . PageSource ) ;
// verify steps for wallet setup are displayed correctly
s . GoToStore ( StoreNavPages . Dashboard ) ;
Assert . True ( s . Driver . FindElement ( By . Id ( "SetupGuide-StoreDone" ) ) . Displayed ) ;
Assert . True ( s . Driver . FindElement ( By . Id ( "SetupGuide-Wallet" ) ) . Displayed ) ;
Assert . True ( s . Driver . FindElement ( By . Id ( "SetupGuide-Lightning" ) ) . Displayed ) ;
// setup onchain wallet
s . Driver . FindElement ( By . Id ( "SetupGuide-Wallet" ) ) . Click ( ) ;
s . AddDerivationScheme ( ) ;
s . Driver . AssertNoError ( ) ;
2020-06-24 03:34:09 +02:00
2022-01-14 09:50:29 +01:00
s . GoToStore ( StoreNavPages . Dashboard ) ;
Assert . True ( s . Driver . FindElement ( By . Id ( "SetupGuide-WalletDone" ) ) . Displayed ) ;
2021-12-31 08:59:02 +01:00
2022-01-14 09:50:29 +01:00
// setup offchain wallet
s . Driver . FindElement ( By . Id ( "SetupGuide-Lightning" ) ) . Click ( ) ;
s . AddLightningNode ( ) ;
s . Driver . AssertNoError ( ) ;
var successAlert = s . FindAlertMessage ( ) ;
Assert . Contains ( "BTC Lightning node updated." , successAlert . Text ) ;
2021-12-31 08:59:02 +01:00
2022-01-14 09:50:29 +01:00
s . ClickOnAllSectionLinks ( ) ;
s . GoToStore ( StoreNavPages . Dashboard ) ;
Assert . True ( s . Driver . FindElement ( By . Id ( "SetupGuide-LightningDone" ) ) . Displayed ) ;
s . GoToInvoices ( ) ;
Assert . Contains ( "There are no invoices matching your criteria." , s . Driver . PageSource ) ;
var invoiceId = s . CreateInvoice ( ) ;
s . FindAlertMessage ( ) ;
s . Driver . FindElement ( By . ClassName ( "invoice-details-link" ) ) . Click ( ) ;
var invoiceUrl = s . Driver . Url ;
//let's test archiving an invoice
Assert . DoesNotContain ( "Archived" , s . Driver . FindElement ( By . Id ( "btn-archive-toggle" ) ) . Text ) ;
s . Driver . FindElement ( By . Id ( "btn-archive-toggle" ) ) . Click ( ) ;
Assert . Contains ( "Unarchive" , s . Driver . FindElement ( By . Id ( "btn-archive-toggle" ) ) . Text ) ;
//check that it no longer appears in list
s . GoToInvoices ( ) ;
Assert . DoesNotContain ( invoiceId , s . Driver . PageSource ) ;
//ok, let's unarchive and see that it shows again
s . Driver . Navigate ( ) . GoToUrl ( invoiceUrl ) ;
s . Driver . FindElement ( By . Id ( "btn-archive-toggle" ) ) . Click ( ) ;
s . FindAlertMessage ( ) ;
Assert . DoesNotContain ( "Unarchive" , s . Driver . FindElement ( By . Id ( "btn-archive-toggle" ) ) . Text ) ;
s . GoToInvoices ( ) ;
Assert . Contains ( invoiceId , s . Driver . PageSource ) ;
// archive via list
s . Driver . FindElement ( By . CssSelector ( $".selector[value=\" { invoiceId } \ "]" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "ActionsDropdownToggle" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "ActionsDropdownArchive" ) ) . Click ( ) ;
Assert . Contains ( "1 invoice archived" , s . FindAlertMessage ( ) . Text ) ;
Assert . DoesNotContain ( invoiceId , s . Driver . PageSource ) ;
// unarchive via list
s . Driver . FindElement ( By . Id ( "SearchOptionsToggle" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "SearchOptionsIncludeArchived" ) ) . Click ( ) ;
Assert . Contains ( invoiceId , s . Driver . PageSource ) ;
s . Driver . FindElement ( By . CssSelector ( $".selector[value=\" { invoiceId } \ "]" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "ActionsDropdownToggle" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "ActionsDropdownUnarchive" ) ) . Click ( ) ;
Assert . Contains ( "1 invoice unarchived" , s . FindAlertMessage ( ) . Text ) ;
Assert . Contains ( invoiceId , s . Driver . PageSource ) ;
// When logout out we should not be able to access store and invoice details
s . Logout ( ) ;
s . GoToUrl ( storeUrl ) ;
Assert . Contains ( "ReturnUrl" , s . Driver . Url ) ;
s . Driver . Navigate ( ) . GoToUrl ( invoiceUrl ) ;
Assert . Contains ( "ReturnUrl" , s . Driver . Url ) ;
s . GoToRegister ( ) ;
// When logged in as different user we should not be able to access store and invoice details
var bob = s . RegisterNewUser ( ) ;
s . GoToUrl ( storeUrl ) ;
Assert . Contains ( "ReturnUrl" , s . Driver . Url ) ;
s . Driver . Navigate ( ) . GoToUrl ( invoiceUrl ) ;
s . AssertAccessDenied ( ) ;
s . GoToHome ( ) ;
s . Logout ( ) ;
// Let's add Bob as a guest to alice's store
s . LogIn ( alice ) ;
s . 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
s . LogIn ( bob ) ;
s . GoToUrl ( storeUrl ) ;
Assert . Contains ( "ReturnUrl" , s . Driver . Url ) ;
s . GoToUrl ( invoiceUrl ) ;
s . Driver . AssertNoError ( ) ;
s . Logout ( ) ;
s . LogIn ( alice ) ;
2022-01-24 12:00:42 +01:00
// Check if we can enable the payment button
s . GoToStore ( StoreNavPages . PayButton ) ;
s . Driver . FindElement ( By . Id ( "enable-pay-button" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "disable-pay-button" ) ) . Click ( ) ;
s . FindAlertMessage ( ) ;
2022-01-26 06:55:48 +01:00
s . GoToStore ( StoreNavPages . General ) ;
2022-01-24 12:00:42 +01:00
Assert . False ( s . Driver . FindElement ( By . Id ( "AnyoneCanCreateInvoice" ) ) . Selected ) ;
s . Driver . SetCheckbox ( By . Id ( "AnyoneCanCreateInvoice" ) , true ) ;
s . Driver . FindElement ( By . Id ( "Save" ) ) . Click ( ) ;
s . FindAlertMessage ( ) ;
Assert . True ( s . Driver . FindElement ( By . Id ( "AnyoneCanCreateInvoice" ) ) . Selected ) ;
// Alice should be able to delete the store
2022-01-18 02:19:27 +01:00
s . GoToStore ( StoreNavPages . General ) ;
2022-01-14 09:50:29 +01:00
s . Driver . FindElement ( By . Id ( "DeleteStore" ) ) . Click ( ) ;
s . Driver . WaitForElement ( By . Id ( "ConfirmInput" ) ) . SendKeys ( "DELETE" ) ;
s . Driver . FindElement ( By . Id ( "ConfirmContinue" ) ) . Click ( ) ;
s . GoToUrl ( storeUrl ) ;
Assert . Contains ( "ReturnUrl" , s . Driver . Url ) ;
2019-05-13 10:59:15 +02:00
}
2019-10-12 13:35:30 +02:00
[Fact(Timeout = TestTimeout)]
public async Task CanUsePairing ( )
{
2022-01-14 09:50:29 +01:00
using var s = CreateSeleniumTester ( ) ;
await s . StartAsync ( ) ;
s . Driver . Navigate ( ) . GoToUrl ( s . Link ( "/api-access-request" ) ) ;
Assert . Contains ( "ReturnUrl" , s . Driver . Url ) ;
s . GoToRegister ( ) ;
s . RegisterNewUser ( ) ;
s . CreateNewStore ( ) ;
s . AddDerivationScheme ( ) ;
2022-01-19 12:58:02 +01:00
s . GoToStore ( StoreNavPages . Tokens ) ;
2022-01-14 09:50:29 +01:00
s . Driver . FindElement ( By . Id ( "CreateNewToken" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "RequestPairing" ) ) . Click ( ) ;
var pairingCode = AssertUrlHasPairingCode ( s ) ;
2019-10-12 13:35:30 +02:00
2022-01-14 09:50:29 +01:00
s . Driver . FindElement ( By . Id ( "ApprovePairing" ) ) . Click ( ) ;
s . FindAlertMessage ( ) ;
Assert . Contains ( pairingCode , s . Driver . PageSource ) ;
2019-10-12 13:35:30 +02:00
2022-01-14 09:50:29 +01:00
var client = new NBitpayClient . Bitpay ( new Key ( ) , s . ServerUri ) ;
await client . AuthorizeClient ( new NBitpayClient . PairingCode ( pairingCode ) ) ;
await client . CreateInvoiceAsync (
new NBitpayClient . Invoice ( ) { Price = 1.000000012 m , Currency = "USD" , FullNotifications = true } ,
NBitpayClient . Facade . Merchant ) ;
2019-10-12 13:35:30 +02:00
2022-01-14 09:50:29 +01:00
client = new NBitpayClient . Bitpay ( new Key ( ) , s . ServerUri ) ;
2019-11-03 08:16:52 +01:00
2022-01-14 09:50:29 +01:00
var code = await client . RequestClientAuthorizationAsync ( "hehe" , NBitpayClient . Facade . Merchant ) ;
s . Driver . Navigate ( ) . GoToUrl ( code . CreateLink ( s . ServerUri ) ) ;
s . Driver . FindElement ( By . Id ( "ApprovePairing" ) ) . Click ( ) ;
await client . CreateInvoiceAsync (
new NBitpayClient . Invoice ( ) { Price = 1.000000012 m , Currency = "USD" , FullNotifications = true } ,
NBitpayClient . Facade . Merchant ) ;
s . Driver . Navigate ( ) . GoToUrl ( s . Link ( "/api-tokens" ) ) ;
s . Driver . FindElement ( By . Id ( "RequestPairing" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "ApprovePairing" ) ) . Click ( ) ;
AssertUrlHasPairingCode ( s ) ;
2019-10-12 13:35:30 +02:00
}
2019-10-06 15:24:28 +02:00
[Fact(Timeout = TestTimeout)]
2019-10-07 09:04:25 +02:00
public async Task CanCreateAppPoS ( )
2019-05-12 10:13:26 +02:00
{
2022-01-14 09:50:29 +01:00
using var s = CreateSeleniumTester ( ) ;
await s . StartAsync ( ) ;
s . RegisterNewUser ( ) ;
s . CreateNewStore ( ) ;
s . Driver . FindElement ( By . Id ( "StoreNav-CreateApp" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Name ( "AppName" ) ) . SendKeys ( "PoS" + Guid . NewGuid ( ) ) ;
s . Driver . FindElement ( By . Id ( "SelectedAppType" ) ) . SendKeys ( "Point of Sale" ) ;
s . Driver . FindElement ( By . Id ( "Create" ) ) . Click ( ) ;
2022-02-07 10:37:45 +01:00
Assert . Contains ( "App successfully created" , s . FindAlertMessage ( ) . Text ) ;
2022-01-14 09:50:29 +01:00
s . Driver . FindElement ( By . CssSelector ( ".template-item:nth-of-type(1) .btn-primary" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "BuyButtonText" ) ) . SendKeys ( "Take my money" ) ;
s . Driver . FindElement ( By . Id ( "SaveItemChanges" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "ToggleRawEditor" ) ) . Click ( ) ;
var template = s . Driver . FindElement ( By . Id ( "Template" ) ) . GetAttribute ( "value" ) ;
Assert . Contains ( "buyButtonText: Take my money" , template ) ;
s . Driver . FindElement ( By . Id ( "DefaultView" ) ) . SendKeys ( "Item list and cart" ) ;
s . Driver . FindElement ( By . Id ( "SaveSettings" ) ) . Click ( ) ;
2022-02-07 10:37:45 +01:00
Assert . Contains ( "App updated" , s . FindAlertMessage ( ) . Text ) ;
2022-01-14 09:50:29 +01:00
s . Driver . FindElement ( By . Id ( "ViewApp" ) ) . Click ( ) ;
2022-02-07 10:37:45 +01:00
var windows = s . Driver . WindowHandles ;
Assert . Equal ( 2 , windows . Count ) ;
s . Driver . SwitchTo ( ) . Window ( windows [ 1 ] ) ;
2022-01-14 09:50:29 +01:00
2022-02-07 10:37:45 +01:00
var posBaseUrl = s . Driver . Url . Replace ( "/cart" , "" ) ;
2022-01-14 09:50:29 +01:00
Assert . True ( s . Driver . PageSource . Contains ( "Tea shop" ) , "Unable to create PoS" ) ;
Assert . True ( s . Driver . PageSource . Contains ( "Cart" ) , "PoS not showing correct default view" ) ;
Assert . True ( s . Driver . PageSource . Contains ( "Take my money" ) , "PoS not showing correct default view" ) ;
s . Driver . Url = posBaseUrl + "/static" ;
Assert . False ( s . Driver . PageSource . Contains ( "Cart" ) , "Static PoS not showing correct view" ) ;
s . Driver . Url = posBaseUrl + "/cart" ;
Assert . True ( s . Driver . PageSource . Contains ( "Cart" ) , "Cart PoS not showing correct view" ) ;
2022-02-07 10:37:45 +01:00
s . Driver . Close ( ) ;
s . Driver . SwitchTo ( ) . Window ( windows [ 0 ] ) ;
2019-05-12 10:13:26 +02:00
}
2019-10-06 15:24:28 +02:00
[Fact(Timeout = TestTimeout)]
2021-01-25 14:10:19 +01:00
public async Task CanCreateCrowdfundingApp ( )
2019-05-12 10:13:26 +02:00
{
2022-01-14 09:50:29 +01:00
using var s = CreateSeleniumTester ( ) ;
await s . StartAsync ( ) ;
s . RegisterNewUser ( ) ;
s . CreateNewStore ( ) ;
s . AddDerivationScheme ( ) ;
s . Driver . FindElement ( By . Id ( "StoreNav-CreateApp" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Name ( "AppName" ) ) . SendKeys ( "CF" + Guid . NewGuid ( ) ) ;
s . Driver . FindElement ( By . Id ( "SelectedAppType" ) ) . SendKeys ( "Crowdfund" ) ;
s . Driver . FindElement ( By . Id ( "Create" ) ) . Click ( ) ;
2022-02-07 10:37:45 +01:00
Assert . Contains ( "App successfully created" , s . FindAlertMessage ( ) . Text ) ;
2022-01-14 09:50:29 +01:00
s . Driver . FindElement ( By . Id ( "Title" ) ) . SendKeys ( "Kukkstarter" ) ;
s . Driver . FindElement ( By . CssSelector ( "div.note-editable.card-block" ) ) . SendKeys ( "1BTC = 1BTC" ) ;
2022-02-07 10:37:45 +01:00
s . Driver . FindElement ( By . Id ( "TargetCurrency" ) ) . Clear ( ) ;
2022-01-14 09:50:29 +01:00
s . Driver . FindElement ( By . Id ( "TargetCurrency" ) ) . SendKeys ( "JPY" ) ;
s . Driver . FindElement ( By . Id ( "TargetAmount" ) ) . SendKeys ( "700" ) ;
s . Driver . FindElement ( By . Id ( "SaveSettings" ) ) . Click ( ) ;
2022-02-07 10:37:45 +01:00
Assert . Contains ( "App updated" , s . FindAlertMessage ( ) . Text ) ;
2022-01-14 09:50:29 +01:00
s . Driver . FindElement ( By . Id ( "ViewApp" ) ) . Click ( ) ;
2022-02-07 10:37:45 +01:00
var windows = s . Driver . WindowHandles ;
Assert . Equal ( 2 , windows . Count ) ;
s . Driver . SwitchTo ( ) . Window ( windows [ 1 ] ) ;
2022-01-14 09:50:29 +01:00
Assert . Equal ( "currently active!" ,
s . Driver . FindElement ( By . CssSelector ( "[data-test='time-state']" ) ) . Text ) ;
2022-02-07 10:37:45 +01:00
s . Driver . Close ( ) ;
s . Driver . SwitchTo ( ) . Window ( windows [ 0 ] ) ;
2019-05-12 10:13:26 +02:00
}
2019-10-06 15:24:28 +02:00
[Fact(Timeout = TestTimeout)]
2019-10-07 09:04:25 +02:00
public async Task CanCreatePayRequest ( )
2019-05-12 10:13:26 +02:00
{
2022-01-14 09:50:29 +01:00
using var s = CreateSeleniumTester ( ) ;
await s . StartAsync ( ) ;
s . RegisterNewUser ( ) ;
s . CreateNewStore ( ) ;
s . AddDerivationScheme ( ) ;
s . Driver . FindElement ( By . Id ( "StoreNav-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" ) ) . Click ( ) ;
var aaa = s . Driver . PageSource ;
var url = s . Driver . Url ;
s . Driver . FindElement ( By . Id ( "ViewAppButton" ) ) . Click ( ) ;
s . Driver . SwitchTo ( ) . Window ( s . Driver . WindowHandles . Last ( ) ) ;
Assert . Equal ( "Amount due" , s . Driver . FindElement ( By . CssSelector ( "[data-test='amount-due-title']" ) ) . Text ) ;
Assert . Equal ( "Pay Invoice" ,
s . Driver . FindElement ( By . CssSelector ( "[data-test='pay-button']" ) ) . Text . Trim ( ) ) ;
// expire
s . Driver . SwitchTo ( ) . Window ( s . Driver . WindowHandles . First ( ) ) ;
s . Driver . ExecuteJavaScript ( "document.getElementById('ExpiryDate').value = '2021-01-21T21:00:00.000Z'" ) ;
s . Driver . FindElement ( By . Id ( "SaveButton" ) ) . Click ( ) ;
s . Driver . SwitchTo ( ) . Window ( s . Driver . WindowHandles . Last ( ) ) ;
s . Driver . Navigate ( ) . Refresh ( ) ;
Assert . Equal ( "Expired" , s . Driver . WaitForElement ( By . CssSelector ( "[data-test='status']" ) ) . Text ) ;
// unexpire
s . Driver . SwitchTo ( ) . Window ( s . Driver . WindowHandles . First ( ) ) ;
s . Driver . FindElement ( By . Id ( "ClearExpiryDate" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "SaveButton" ) ) . Click ( ) ;
s . Driver . SwitchTo ( ) . Window ( s . Driver . WindowHandles . Last ( ) ) ;
s . Driver . Navigate ( ) . Refresh ( ) ;
s . Driver . AssertElementNotFound ( By . CssSelector ( "[data-test='status']" ) ) ;
Assert . Equal ( "Pay Invoice" ,
s . Driver . FindElement ( By . CssSelector ( "[data-test='pay-button']" ) ) . Text . Trim ( ) ) ;
2019-05-12 10:13:26 +02:00
}
2020-03-23 07:46:54 +01:00
[Fact(Timeout = TestTimeout)]
public async Task CanUseCoinSelection ( )
{
2022-01-14 09:50:29 +01:00
using var s = CreateSeleniumTester ( ) ;
await s . StartAsync ( ) ;
s . RegisterNewUser ( true ) ;
( _ , string storeId ) = s . CreateNewStore ( ) ;
s . GenerateWallet ( "BTC" , "" , false , true ) ;
var walletId = new WalletId ( storeId , "BTC" ) ;
s . GoToWallet ( walletId , WalletsNavPages . Receive ) ;
s . Driver . FindElement ( By . Id ( "generateButton" ) ) . Click ( ) ;
var addressStr = s . Driver . FindElement ( By . Id ( "address" ) ) . GetProperty ( "value" ) ;
var address = BitcoinAddress . Create ( addressStr ,
( ( BTCPayNetwork ) s . Server . NetworkProvider . GetNetwork ( "BTC" ) ) . NBitcoinNetwork ) ;
await s . Server . ExplorerNode . GenerateAsync ( 1 ) ;
for ( int i = 0 ; i < 6 ; i + + )
2020-03-23 07:46:54 +01:00
{
2022-01-14 09:50:29 +01:00
await s . Server . ExplorerNode . SendToAddressAsync ( address , Money . Coins ( 1.0 m ) ) ;
2020-03-23 07:46:54 +01:00
}
2022-01-14 09:50:29 +01:00
var targetTx = await s . Server . ExplorerNode . SendToAddressAsync ( address , Money . Coins ( 1.2 m ) ) ;
var tx = await s . Server . ExplorerNode . GetRawTransactionAsync ( targetTx ) ;
var spentOutpoint = new OutPoint ( targetTx ,
tx . Outputs . FindIndex ( txout = > txout . Value = = Money . Coins ( 1.2 m ) ) ) ;
await TestUtils . EventuallyAsync ( async ( ) = >
{
var store = await s . Server . PayTester . StoreRepository . FindStore ( storeId ) ;
var x = store . GetSupportedPaymentMethods ( s . Server . NetworkProvider )
. OfType < DerivationSchemeSettings > ( )
. Single ( settings = > settings . PaymentId . CryptoCode = = walletId . CryptoCode ) ;
var wallet = s . Server . PayTester . GetService < BTCPayWalletProvider > ( ) . GetWallet ( walletId . CryptoCode ) ;
wallet . InvalidateCache ( x . AccountDerivation ) ;
Assert . Contains (
await wallet . GetUnspentCoins ( x . AccountDerivation ) ,
coin = > coin . OutPoint = = spentOutpoint ) ;
} ) ;
await s . Server . ExplorerNode . GenerateAsync ( 1 ) ;
s . GoToWallet ( walletId ) ;
s . Driver . WaitForAndClick ( By . Id ( "toggleInputSelection" ) ) ;
s . Driver . WaitForElement ( By . Id ( spentOutpoint . ToString ( ) ) ) ;
Assert . Equal ( "true" ,
s . Driver . FindElement ( By . Name ( "InputSelection" ) ) . GetAttribute ( "value" ) . ToLowerInvariant ( ) ) ;
var el = s . Driver . FindElement ( By . Id ( spentOutpoint . ToString ( ) ) ) ;
s . Driver . FindElement ( By . Id ( spentOutpoint . ToString ( ) ) ) . Click ( ) ;
var inputSelectionSelect = s . Driver . FindElement ( By . Name ( "SelectedInputs" ) ) ;
Assert . Single ( inputSelectionSelect . FindElements ( By . CssSelector ( "[selected]" ) ) ) ;
var bob = new Key ( ) . PubKey . Hash . GetAddress ( Network . RegTest ) ;
SetTransactionOutput ( s , 0 , bob , 0.3 m ) ;
s . Driver . FindElement ( By . Id ( "SignTransaction" ) ) . Click ( ) ;
s . Driver . FindElement ( By . CssSelector ( "button[value=broadcast]" ) ) . Click ( ) ;
var happyElement = s . FindAlertMessage ( ) ;
var happyText = happyElement . Text ;
var txid = Regex . Match ( happyText , @"\((.*)\)" ) . Groups [ 1 ] . Value ;
tx = await s . Server . ExplorerNode . GetRawTransactionAsync ( new uint256 ( txid ) ) ;
Assert . Single ( tx . Inputs ) ;
Assert . Equal ( spentOutpoint , tx . Inputs [ 0 ] . PrevOut ) ;
2020-03-23 07:46:54 +01:00
}
2020-11-06 12:42:26 +01:00
[Fact(Timeout = TestTimeout)]
public async Task CanUseWebhooks ( )
{
2022-01-14 09:50:29 +01:00
using var s = CreateSeleniumTester ( ) ;
await s . StartAsync ( ) ;
s . RegisterNewUser ( true ) ;
s . CreateNewStore ( ) ;
s . GoToStore ( StoreNavPages . Webhooks ) ;
2020-11-06 12:42:26 +01:00
2022-01-14 09:50:29 +01:00
TestLogs . LogInformation ( "Let's create two webhooks" ) ;
for ( var i = 0 ; i < 2 ; i + + )
{
s . Driver . FindElement ( By . Id ( "CreateWebhook" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Name ( "PayloadUrl" ) ) . SendKeys ( $"http://127.0.0.1/callback{i}" ) ;
new SelectElement ( s . Driver . FindElement ( By . Id ( "Everything" ) ) ) . SelectByValue ( "false" ) ;
s . Driver . FindElement ( By . Id ( "InvoiceCreated" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "InvoiceProcessing" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Name ( "add" ) ) . Click ( ) ;
}
2020-11-06 12:42:26 +01:00
2022-01-14 09:50:29 +01:00
TestLogs . LogInformation ( "Let's delete one of them" ) ;
var deletes = s . Driver . FindElements ( By . LinkText ( "Delete" ) ) ;
Assert . Equal ( 2 , deletes . Count ) ;
deletes [ 0 ] . Click ( ) ;
s . Driver . WaitForElement ( By . Id ( "ConfirmInput" ) ) . SendKeys ( "DELETE" ) ;
s . Driver . FindElement ( By . Id ( "ConfirmContinue" ) ) . Click ( ) ;
deletes = s . Driver . FindElements ( By . LinkText ( "Delete" ) ) ;
Assert . Single ( deletes ) ;
s . FindAlertMessage ( ) ;
TestLogs . LogInformation ( "Let's try to update one of them" ) ;
s . Driver . FindElement ( By . LinkText ( "Modify" ) ) . Click ( ) ;
using FakeServer server = new FakeServer ( ) ;
await server . Start ( ) ;
s . Driver . FindElement ( By . Name ( "PayloadUrl" ) ) . Clear ( ) ;
s . Driver . FindElement ( By . Name ( "PayloadUrl" ) ) . SendKeys ( server . ServerUri . AbsoluteUri ) ;
s . Driver . FindElement ( By . Name ( "Secret" ) ) . Clear ( ) ;
s . Driver . FindElement ( By . Name ( "Secret" ) ) . SendKeys ( "HelloWorld" ) ;
s . Driver . FindElement ( By . Name ( "update" ) ) . Click ( ) ;
s . FindAlertMessage ( ) ;
s . Driver . FindElement ( By . LinkText ( "Modify" ) ) . Click ( ) ;
foreach ( var value in Enum . GetValues ( typeof ( WebhookEventType ) ) )
{
// Here we make sure we did not forget an event type in the list
// However, maybe some event should not appear here because not at the store level.
// Fix as needed.
Assert . Contains ( $"value=\" { value } \ "" , s . Driver . PageSource ) ;
}
2021-01-22 17:49:26 +01:00
2022-01-14 09:50:29 +01:00
// This one should be checked
Assert . Contains ( $"value=\" InvoiceProcessing \ " checked" , s . Driver . PageSource ) ;
Assert . Contains ( $"value=\" InvoiceCreated \ " checked" , s . Driver . PageSource ) ;
// This one never been checked
Assert . DoesNotContain ( $"value=\" InvoiceReceivedPayment \ " checked" , s . Driver . PageSource ) ;
2020-11-06 12:42:26 +01:00
2022-01-14 09:50:29 +01:00
s . Driver . FindElement ( By . Name ( "update" ) ) . Click ( ) ;
s . FindAlertMessage ( ) ;
Assert . Contains ( server . ServerUri . AbsoluteUri , s . Driver . PageSource ) ;
2020-11-06 12:42:26 +01:00
2022-01-14 09:50:29 +01:00
TestLogs . LogInformation ( "Let's see if we can generate an event" ) ;
2022-01-20 12:52:31 +01:00
s . GoToStore ( ) ;
2022-01-14 09:50:29 +01:00
s . AddDerivationScheme ( ) ;
s . CreateInvoice ( ) ;
var request = await server . GetNextRequest ( ) ;
var headers = request . Request . Headers ;
var actualSig = headers [ "BTCPay-Sig" ] . First ( ) ;
var bytes = await request . Request . Body . ReadBytesAsync ( ( int ) headers . ContentLength . Value ) ;
var expectedSig =
$"sha256={Encoders.Hex.EncodeData(new HMACSHA256(Encoding.UTF8.GetBytes(" HelloWorld ")).ComputeHash(bytes))}" ;
Assert . Equal ( expectedSig , actualSig ) ;
request . Response . StatusCode = 200 ;
server . Done ( ) ;
TestLogs . LogInformation ( "Let's make a failed event" ) ;
s . CreateInvoice ( ) ;
request = await server . GetNextRequest ( ) ;
request . Response . StatusCode = 404 ;
server . Done ( ) ;
// The delivery is done asynchronously, so small wait here
await Task . Delay ( 500 ) ;
s . GoToStore ( StoreNavPages . Webhooks ) ;
s . Driver . FindElement ( By . LinkText ( "Modify" ) ) . Click ( ) ;
var elements = s . Driver . FindElements ( By . ClassName ( "redeliver" ) ) ;
// One worked, one failed
s . Driver . FindElement ( By . ClassName ( "fa-times" ) ) ;
s . Driver . FindElement ( By . ClassName ( "fa-check" ) ) ;
elements [ 0 ] . Click ( ) ;
s . FindAlertMessage ( ) ;
request = await server . GetNextRequest ( ) ;
request . Response . StatusCode = 404 ;
server . Done ( ) ;
TestLogs . LogInformation ( "Can we browse the json content?" ) ;
CanBrowseContent ( s ) ;
2021-01-22 17:49:26 +01:00
2022-01-14 09:50:29 +01:00
s . GoToInvoices ( ) ;
s . Driver . FindElement ( By . LinkText ( "Details" ) ) . Click ( ) ;
CanBrowseContent ( s ) ;
var element = s . Driver . FindElement ( By . ClassName ( "redeliver" ) ) ;
element . Click ( ) ;
s . FindAlertMessage ( ) ;
request = await server . GetNextRequest ( ) ;
request . Response . StatusCode = 404 ;
server . Done ( ) ;
TestLogs . LogInformation ( "Let's see if we can delete store with some webhooks inside" ) ;
2022-01-18 02:19:27 +01:00
s . GoToStore ( StoreNavPages . General ) ;
2022-01-14 09:50:29 +01:00
s . Driver . FindElement ( By . Id ( "DeleteStore" ) ) . Click ( ) ;
s . Driver . WaitForElement ( By . Id ( "ConfirmInput" ) ) . SendKeys ( "DELETE" ) ;
s . Driver . FindElement ( By . Id ( "ConfirmContinue" ) ) . Click ( ) ;
s . FindAlertMessage ( ) ;
2020-11-06 12:42:26 +01:00
}
2019-10-06 15:24:28 +02:00
[Fact(Timeout = TestTimeout)]
2021-10-12 11:37:13 +02:00
public async Task CanImportMnemonic ( )
{
2022-01-14 09:50:29 +01:00
using var s = CreateSeleniumTester ( ) ;
await s . StartAsync ( ) ;
s . RegisterNewUser ( true ) ;
foreach ( var isHotwallet in new [ ] { false , true } )
2021-10-12 11:37:13 +02:00
{
2022-01-14 09:50:29 +01:00
var cryptoCode = "BTC" ;
2022-01-19 12:58:02 +01:00
s . CreateNewStore ( ) ;
2022-01-14 09:50:29 +01:00
s . GenerateWallet ( cryptoCode , "melody lizard phrase voice unique car opinion merge degree evil swift cargo" , privkeys : isHotwallet ) ;
2022-01-19 12:58:02 +01:00
s . GoToWalletSettings ( cryptoCode ) ;
2022-01-14 09:50:29 +01:00
if ( isHotwallet )
Assert . Contains ( "View seed" , s . Driver . PageSource ) ;
else
Assert . DoesNotContain ( "View seed" , s . Driver . PageSource ) ;
2021-10-12 11:37:13 +02:00
}
}
[Fact(Timeout = TestTimeout)]
2019-10-07 09:04:25 +02:00
public async Task CanManageWallet ( )
2019-05-13 10:59:15 +02:00
{
2022-01-14 09:50:29 +01:00
using var s = CreateSeleniumTester ( ) ;
await s . StartAsync ( ) ;
s . RegisterNewUser ( true ) ;
( _ , string storeId ) = s . CreateNewStore ( ) ;
const string cryptoCode = "BTC" ;
// 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
s . GenerateWallet ( cryptoCode , "" , true ) ;
//let's test quickly the receive wallet page
s . Driver . FindElement ( By . Id ( $"StoreNav-Wallet{cryptoCode}" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "SectionNav-Send" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "SignTransaction" ) ) . Click ( ) ;
//you cannot use the Sign with NBX option without saving private keys when generating the wallet.
Assert . DoesNotContain ( "nbx-seed" , s . Driver . PageSource ) ;
s . Driver . FindElement ( By . Id ( "SectionNav-Receive" ) ) . Click ( ) ;
//generate a receiving address
s . Driver . FindElement ( By . CssSelector ( "button[value=generate-new-address]" ) ) . Click ( ) ;
Assert . True ( s . Driver . FindElement ( By . ClassName ( "qr-container" ) ) . Displayed ) ;
var receiveAddr = s . Driver . FindElement ( By . Id ( "address" ) ) . GetAttribute ( "value" ) ;
//unreserve
s . Driver . FindElement ( By . CssSelector ( "button[value=unreserve-current-address]" ) ) . Click ( ) ;
//generate it again, should be the same one as before as nothing got used in the meantime
s . Driver . FindElement ( By . CssSelector ( "button[value=generate-new-address]" ) ) . Click ( ) ;
Assert . True ( s . Driver . FindElement ( By . ClassName ( "qr-container" ) ) . Displayed ) ;
Assert . Equal ( receiveAddr , s . Driver . FindElement ( By . Id ( "address" ) ) . GetAttribute ( "value" ) ) ;
//send money to addr and ensure it changed
var sess = await s . Server . ExplorerClient . CreateWebsocketNotificationSessionAsync ( ) ;
await sess . ListenAllTrackedSourceAsync ( ) ;
var nextEvent = sess . NextEventAsync ( ) ;
await s . Server . ExplorerNode . SendToAddressAsync ( BitcoinAddress . Create ( receiveAddr , Network . RegTest ) ,
Money . Parse ( "0.1" ) ) ;
await nextEvent ;
await Task . Delay ( 200 ) ;
s . Driver . Navigate ( ) . Refresh ( ) ;
s . Driver . FindElement ( By . CssSelector ( "button[value=generate-new-address]" ) ) . Click ( ) ;
Assert . NotEqual ( receiveAddr , s . Driver . FindElement ( By . Id ( "address" ) ) . GetAttribute ( "value" ) ) ;
receiveAddr = s . Driver . FindElement ( By . Id ( "address" ) ) . GetAttribute ( "value" ) ;
//change the wallet and ensure old address is not there and generating a new one does not result in the prev one
s . GenerateWallet ( cryptoCode , "" , true ) ;
2022-01-19 12:58:02 +01:00
s . GoToWallet ( null , WalletsNavPages . Receive ) ;
2022-01-14 09:50:29 +01:00
s . Driver . FindElement ( By . CssSelector ( "button[value=generate-new-address]" ) ) . Click ( ) ;
Assert . NotEqual ( receiveAddr , s . Driver . FindElement ( By . Id ( "address" ) ) . GetAttribute ( "value" ) ) ;
var invoiceId = s . CreateInvoice ( storeId ) ;
var invoice = await s . Server . PayTester . InvoiceRepository . GetInvoice ( invoiceId ) ;
var address = invoice . EntityToDTO ( ) . Addresses [ "BTC" ] ;
//wallet should have been imported to bitcoin core wallet in watch only mode.
var result =
await s . Server . ExplorerNode . GetAddressInfoAsync ( BitcoinAddress . Create ( address , Network . RegTest ) ) ;
Assert . True ( result . IsWatchOnly ) ;
2022-01-20 12:52:31 +01:00
s . GoToStore ( storeId ) ;
2022-01-14 09:50:29 +01:00
var mnemonic = s . GenerateWallet ( cryptoCode , "" , true , true ) ;
//lets import and save private keys
var root = mnemonic . DeriveExtKey ( ) ;
invoiceId = s . CreateInvoice ( storeId ) ;
invoice = await s . Server . PayTester . InvoiceRepository . GetInvoice ( invoiceId ) ;
address = invoice . EntityToDTO ( ) . Addresses [ "BTC" ] ;
result = await s . Server . ExplorerNode . GetAddressInfoAsync (
BitcoinAddress . Create ( address , Network . RegTest ) ) ;
//spendable from bitcoin core wallet!
Assert . False ( result . IsWatchOnly ) ;
var tx = s . Server . ExplorerNode . SendToAddress ( BitcoinAddress . Create ( address , Network . RegTest ) ,
Money . Coins ( 3.0 m ) ) ;
await s . Server . ExplorerNode . GenerateAsync ( 1 ) ;
s . GoToStore ( storeId ) ;
s . Driver . FindElement ( By . Id ( $"StoreNav-Wallet{cryptoCode}" ) ) . Click ( ) ;
s . ClickOnAllSectionLinks ( ) ;
// Make sure wallet info is correct
2022-01-19 12:58:02 +01:00
s . GoToWalletSettings ( cryptoCode ) ;
2022-01-14 09:50:29 +01:00
Assert . Contains ( mnemonic . DeriveExtKey ( ) . GetPublicKey ( ) . GetHDFingerPrint ( ) . ToString ( ) ,
s . Driver . FindElement ( By . Id ( "AccountKeys_0__MasterFingerprint" ) ) . GetAttribute ( "value" ) ) ;
Assert . Contains ( "m/84'/1'/0'" ,
s . Driver . FindElement ( By . Id ( "AccountKeys_0__AccountKeyPath" ) ) . GetAttribute ( "value" ) ) ;
s . Driver . FindElement ( By . Id ( $"StoreNav-Wallet{cryptoCode}" ) ) . Click ( ) ;
// Make sure we can rescan, because we are admin!
s . Driver . FindElement ( By . Id ( "SectionNav-Rescan" ) ) . Click ( ) ;
Assert . Contains ( "The batch size make sure" , s . Driver . PageSource ) ;
// Check the tx sent earlier arrived
s . Driver . FindElement ( By . Id ( "SectionNav-Transactions" ) ) . Click ( ) ;
var walletTransactionLink = s . Driver . Url ;
Assert . Contains ( tx . ToString ( ) , s . Driver . PageSource ) ;
// Send to bob
s . Driver . FindElement ( By . Id ( "SectionNav-Send" ) ) . Click ( ) ;
var bob = new Key ( ) . PubKey . Hash . GetAddress ( Network . RegTest ) ;
SetTransactionOutput ( s , 0 , bob , 1 ) ;
s . Driver . FindElement ( By . Id ( "SignTransaction" ) ) . Click ( ) ;
// 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 ) ;
s . Driver . FindElement ( By . Id ( $"StoreNav-Wallet{cryptoCode}" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "SectionNav-Send" ) ) . Click ( ) ;
var jack = new Key ( ) . PubKey . Hash . GetAddress ( Network . RegTest ) ;
SetTransactionOutput ( s , 0 , jack , 0.01 m ) ;
s . Driver . FindElement ( By . Id ( "SignTransaction" ) ) . Click ( ) ;
Assert . Contains ( jack . ToString ( ) , s . Driver . PageSource ) ;
Assert . Contains ( "0.01000000" , s . Driver . PageSource ) ;
Assert . EndsWith ( "psbt/ready" , s . Driver . Url ) ;
s . Driver . FindElement ( By . CssSelector ( "button[value=broadcast]" ) ) . Click ( ) ;
Assert . Equal ( walletTransactionLink , s . Driver . Url ) ;
var bip21 = invoice . EntityToDTO ( ) . CryptoInfo . First ( ) . PaymentUrls . BIP21 ;
//let's make bip21 more interesting
bip21 + = "&label=Solid Snake&message=Snake? Snake? SNAAAAKE!" ;
var parsedBip21 = new BitcoinUrlBuilder ( bip21 , Network . RegTest ) ;
s . Driver . FindElement ( By . Id ( $"StoreNav-Wallet{cryptoCode}" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "SectionNav-Send" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "bip21parse" ) ) . Click ( ) ;
s . Driver . SwitchTo ( ) . Alert ( ) . SendKeys ( bip21 ) ;
s . Driver . SwitchTo ( ) . Alert ( ) . Accept ( ) ;
s . FindAlertMessage ( StatusMessageModel . StatusSeverity . Info ) ;
Assert . Equal ( parsedBip21 . Amount . ToString ( false ) ,
s . Driver . FindElement ( By . Id ( "Outputs_0__Amount" ) ) . GetAttribute ( "value" ) ) ;
Assert . Equal ( parsedBip21 . Address . ToString ( ) ,
s . Driver . FindElement ( By . Id ( "Outputs_0__DestinationAddress" ) ) . GetAttribute ( "value" ) ) ;
2022-01-19 12:58:02 +01:00
s . GoToWalletSettings ( cryptoCode ) ;
2022-01-14 09:50:29 +01:00
var settingsUrl = s . Driver . Url ;
s . Driver . FindElement ( By . Id ( "ActionsDropdownToggle" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "ViewSeed" ) ) . Click ( ) ;
// Seed backup page
var recoveryPhrase = s . Driver . FindElements ( By . Id ( "RecoveryPhrase" ) ) . First ( )
. GetAttribute ( "data-mnemonic" ) ;
Assert . Equal ( mnemonic . ToString ( ) , recoveryPhrase ) ;
Assert . Contains ( "The recovery phrase will also be stored on the server as a hot wallet." ,
s . Driver . PageSource ) ;
// No confirmation, just a link to return to the wallet
Assert . Empty ( s . Driver . FindElements ( By . Id ( "confirm" ) ) ) ;
s . Driver . FindElement ( By . Id ( "proceed" ) ) . Click ( ) ;
Assert . Equal ( settingsUrl , s . Driver . Url ) ;
2019-05-12 10:13:26 +02:00
}
2020-06-24 03:34:09 +02:00
2021-08-03 07:27:04 +02:00
[Fact(Timeout = TestTimeout)]
public async Task CanImportWallet ( )
{
2022-01-14 09:50:29 +01:00
using var s = CreateSeleniumTester ( ) ;
await s . StartAsync ( ) ;
s . RegisterNewUser ( true ) ;
2022-01-19 12:58:02 +01:00
s . CreateNewStore ( ) ;
2022-01-14 09:50:29 +01:00
const string cryptoCode = "BTC" ;
var mnemonic = s . GenerateWallet ( cryptoCode , "click chunk owner kingdom faint steak safe evidence bicycle repeat bulb wheel" ) ;
// Make sure wallet info is correct
2022-01-19 12:58:02 +01:00
s . GoToWalletSettings ( cryptoCode ) ;
2022-01-14 09:50:29 +01:00
Assert . Contains ( mnemonic . DeriveExtKey ( ) . GetPublicKey ( ) . GetHDFingerPrint ( ) . ToString ( ) ,
s . Driver . FindElement ( By . Id ( "AccountKeys_0__MasterFingerprint" ) ) . GetAttribute ( "value" ) ) ;
Assert . Contains ( "m/84'/1'/0'" ,
s . Driver . FindElement ( By . Id ( "AccountKeys_0__AccountKeyPath" ) ) . GetAttribute ( "value" ) ) ;
2021-08-03 07:27:04 +02:00
}
2020-06-24 03:34:09 +02:00
[Fact]
[Trait("Selenium", "Selenium")]
2021-10-18 05:37:59 +02:00
[Trait("Lightning", "Lightning")]
2020-06-24 03:34:09 +02:00
public async Task CanUsePullPaymentsViaUI ( )
{
2021-11-22 09:16:08 +01:00
using var s = CreateSeleniumTester ( ) ;
2021-11-26 07:02:30 +01:00
s . Server . ActivateLightning ( LightningConnectionType . LndREST ) ;
2021-06-30 09:59:01 +02:00
await s . StartAsync ( ) ;
2021-11-26 07:02:30 +01:00
await s . Server . EnsureChannelsSetup ( ) ;
2021-06-30 09:59:01 +02:00
s . RegisterNewUser ( true ) ;
s . CreateNewStore ( ) ;
s . GenerateWallet ( "BTC" , "" , true , true ) ;
await s . Server . ExplorerNode . GenerateAsync ( 1 ) ;
await s . FundStoreWallet ( denomination : 50.0 m ) ;
2021-10-22 04:17:40 +02:00
s . GoToStore ( s . StoreId , StoreNavPages . PullPayments ) ;
2021-06-30 09:59:01 +02:00
s . Driver . FindElement ( By . Id ( "NewPullPayment" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "Name" ) ) . SendKeys ( "PP1" ) ;
s . Driver . FindElement ( By . Id ( "Amount" ) ) . Clear ( ) ;
2021-10-29 11:01:16 +02:00
s . Driver . FindElement ( By . Id ( "Amount" ) ) . SendKeys ( "99.0" ) ;
2021-06-30 09:59:01 +02:00
s . Driver . FindElement ( By . Id ( "Create" ) ) . Click ( ) ;
s . Driver . FindElement ( By . LinkText ( "View" ) ) . Click ( ) ;
2021-10-22 04:17:40 +02:00
s . GoToStore ( s . StoreId , StoreNavPages . PullPayments ) ;
2021-06-30 09:59:01 +02:00
s . Driver . FindElement ( By . Id ( "NewPullPayment" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "Name" ) ) . SendKeys ( "PP2" ) ;
s . Driver . FindElement ( By . Id ( "Amount" ) ) . Clear ( ) ;
s . Driver . FindElement ( By . Id ( "Amount" ) ) . SendKeys ( "100.0" ) ;
s . Driver . FindElement ( By . Id ( "Create" ) ) . Click ( ) ;
// This should select the first View, ie, the last one PP2
s . Driver . FindElement ( By . LinkText ( "View" ) ) . Click ( ) ;
var address = await s . Server . ExplorerNode . GetNewAddressAsync ( ) ;
s . Driver . FindElement ( By . Id ( "Destination" ) ) . SendKeys ( address . ToString ( ) ) ;
s . Driver . FindElement ( By . Id ( "ClaimedAmount" ) ) . Clear ( ) ;
s . Driver . FindElement ( By . Id ( "ClaimedAmount" ) ) . SendKeys ( "15" + Keys . Enter ) ;
s . FindAlertMessage ( ) ;
// We should not be able to use an address already used
s . Driver . FindElement ( By . Id ( "Destination" ) ) . SendKeys ( address . ToString ( ) ) ;
s . Driver . FindElement ( By . Id ( "ClaimedAmount" ) ) . Clear ( ) ;
s . Driver . FindElement ( By . Id ( "ClaimedAmount" ) ) . SendKeys ( "20" + Keys . Enter ) ;
s . FindAlertMessage ( StatusMessageModel . StatusSeverity . Error ) ;
address = await s . Server . ExplorerNode . GetNewAddressAsync ( ) ;
s . Driver . FindElement ( By . Id ( "Destination" ) ) . Clear ( ) ;
s . Driver . FindElement ( By . Id ( "Destination" ) ) . SendKeys ( address . ToString ( ) ) ;
s . Driver . FindElement ( By . Id ( "ClaimedAmount" ) ) . Clear ( ) ;
s . Driver . FindElement ( By . Id ( "ClaimedAmount" ) ) . SendKeys ( "20" + Keys . Enter ) ;
s . FindAlertMessage ( ) ;
Assert . Contains ( "Awaiting Approval" , s . Driver . PageSource ) ;
var viewPullPaymentUrl = s . Driver . Url ;
// This one should have nothing
2021-10-22 04:17:40 +02:00
s . GoToStore ( s . StoreId , StoreNavPages . PullPayments ) ;
2021-06-30 09:59:01 +02:00
var payouts = s . Driver . FindElements ( By . ClassName ( "pp-payout" ) ) ;
Assert . Equal ( 2 , payouts . Count ) ;
payouts [ 1 ] . Click ( ) ;
Assert . Empty ( s . Driver . FindElements ( By . ClassName ( "payout" ) ) ) ;
// PP2 should have payouts
2021-10-22 04:17:40 +02:00
s . GoToStore ( s . StoreId , StoreNavPages . PullPayments ) ;
2021-06-30 09:59:01 +02:00
payouts = s . Driver . FindElements ( By . ClassName ( "pp-payout" ) ) ;
payouts [ 0 ] . Click ( ) ;
2021-10-29 11:01:16 +02:00
2021-06-30 09:59:01 +02:00
Assert . NotEmpty ( s . Driver . FindElements ( By . ClassName ( "payout" ) ) ) ;
s . Driver . FindElement ( By . Id ( $"{PayoutState.AwaitingApproval}-selectAllCheckbox" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( $"{PayoutState.AwaitingApproval}-actions" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( $"{PayoutState.AwaitingApproval}-approve-pay" ) ) . Click ( ) ;
2021-05-19 04:39:27 +02:00
2021-06-30 09:59:01 +02:00
s . Driver . FindElement ( By . Id ( "SignTransaction" ) ) . Click ( ) ;
s . Driver . FindElement ( By . CssSelector ( "button[value=broadcast]" ) ) . Click ( ) ;
s . FindAlertMessage ( ) ;
2020-06-24 03:34:09 +02:00
2021-06-30 09:59:01 +02:00
TestUtils . Eventually ( ( ) = >
{
s . Driver . Navigate ( ) . Refresh ( ) ;
Assert . Contains ( "badge transactionLabel" , s . Driver . PageSource ) ;
} ) ;
Assert . Equal ( "payout" , s . Driver . FindElement ( By . ClassName ( "transactionLabel" ) ) . Text ) ;
2021-10-22 04:17:40 +02:00
s . GoToStore ( s . StoreId , StoreNavPages . Payouts ) ;
2021-06-30 09:59:01 +02:00
s . Driver . FindElement ( By . Id ( $"{PayoutState.InProgress}-view" ) ) . Click ( ) ;
ReadOnlyCollection < IWebElement > txs ;
TestUtils . Eventually ( ( ) = >
{
s . Driver . Navigate ( ) . Refresh ( ) ;
2021-10-29 11:01:16 +02:00
2020-06-24 03:34:09 +02:00
txs = s . Driver . FindElements ( By . ClassName ( "transaction-link" ) ) ;
Assert . Equal ( 2 , txs . Count ) ;
2021-06-30 09:59:01 +02:00
} ) ;
2020-06-24 03:34:09 +02:00
2021-06-30 09:59:01 +02:00
s . Driver . Navigate ( ) . GoToUrl ( viewPullPaymentUrl ) ;
txs = s . Driver . FindElements ( By . ClassName ( "transaction-link" ) ) ;
Assert . Equal ( 2 , txs . Count ) ;
Assert . Contains ( PayoutState . InProgress . GetStateString ( ) , s . Driver . PageSource ) ;
2020-06-24 03:34:09 +02:00
2021-06-30 09:59:01 +02:00
await s . Server . ExplorerNode . GenerateAsync ( 1 ) ;
2020-06-24 03:34:09 +02:00
2021-06-30 09:59:01 +02:00
TestUtils . Eventually ( ( ) = >
{
s . Driver . Navigate ( ) . Refresh ( ) ;
Assert . Contains ( PayoutState . Completed . GetStateString ( ) , s . Driver . PageSource ) ;
} ) ;
await s . Server . ExplorerNode . GenerateAsync ( 10 ) ;
var pullPaymentId = viewPullPaymentUrl . Split ( '/' ) . Last ( ) ;
await TestUtils . EventuallyAsync ( async ( ) = >
{
using var ctx = s . Server . PayTester . GetService < ApplicationDbContextFactory > ( ) . CreateContext ( ) ;
var payoutsData = await ctx . Payouts . Where ( p = > p . PullPaymentDataId = = pullPaymentId ) . ToListAsync ( ) ;
Assert . True ( payoutsData . All ( p = > p . State = = PayoutState . Completed ) ) ;
} ) ;
2021-07-16 09:57:37 +02:00
s . GoToHome ( ) ;
//offline/external payout test
2021-12-11 04:32:23 +01:00
s . Driver . FindElement ( By . Id ( "NotificationsHandle" ) ) . Click ( ) ;
2021-07-16 09:57:37 +02:00
s . Driver . FindElement ( By . CssSelector ( "#notificationsForm button" ) ) . Click ( ) ;
2021-12-31 08:59:02 +01:00
2021-07-16 09:57:37 +02:00
var newStore = s . CreateNewStore ( ) ;
s . GenerateWallet ( "BTC" , "" , true , true ) ;
2021-10-22 04:17:40 +02:00
s . GoToStore ( s . StoreId , StoreNavPages . PullPayments ) ;
2021-10-29 11:01:16 +02:00
2021-07-16 09:57:37 +02:00
s . Driver . FindElement ( By . Id ( "NewPullPayment" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "Name" ) ) . SendKeys ( "External Test" ) ;
s . Driver . FindElement ( By . Id ( "Amount" ) ) . Clear ( ) ;
s . Driver . FindElement ( By . Id ( "Amount" ) ) . SendKeys ( "0.001" ) ;
s . Driver . FindElement ( By . Id ( "Currency" ) ) . Clear ( ) ;
s . Driver . FindElement ( By . Id ( "Currency" ) ) . SendKeys ( "BTC" ) ;
s . Driver . FindElement ( By . Id ( "Create" ) ) . Click ( ) ;
s . Driver . FindElement ( By . LinkText ( "View" ) ) . Click ( ) ;
2021-10-29 11:01:16 +02:00
2021-07-16 09:57:37 +02:00
address = await s . Server . ExplorerNode . GetNewAddressAsync ( ) ;
s . Driver . FindElement ( By . Id ( "Destination" ) ) . SendKeys ( address . ToString ( ) ) ;
s . Driver . FindElement ( By . Id ( "ClaimedAmount" ) ) . SendKeys ( Keys . Enter ) ;
s . FindAlertMessage ( ) ;
Assert . Contains ( PayoutState . AwaitingApproval . GetStateString ( ) , s . Driver . PageSource ) ;
2021-10-22 04:17:40 +02:00
s . GoToStore ( s . StoreId , StoreNavPages . Payouts ) ;
2021-07-16 09:57:37 +02:00
s . Driver . FindElement ( By . Id ( $"{PayoutState.AwaitingApproval}-view" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( $"{PayoutState.AwaitingApproval}-selectAllCheckbox" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( $"{PayoutState.AwaitingApproval}-actions" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( $"{PayoutState.AwaitingApproval}-approve" ) ) . Click ( ) ;
s . FindAlertMessage ( ) ;
2021-10-29 11:01:16 +02:00
var tx = await s . Server . ExplorerNode . SendToAddressAsync ( address , Money . FromUnit ( 0.001 m , MoneyUnit . BTC ) ) ;
2021-07-16 09:57:37 +02:00
2021-10-22 04:17:40 +02:00
s . GoToStore ( s . StoreId , StoreNavPages . Payouts ) ;
2021-10-29 11:01:16 +02:00
2021-07-16 09:57:37 +02:00
s . Driver . FindElement ( By . Id ( $"{PayoutState.AwaitingPayment}-view" ) ) . Click ( ) ;
Assert . Contains ( PayoutState . AwaitingPayment . GetStateString ( ) , s . Driver . PageSource ) ;
s . Driver . FindElement ( By . Id ( $"{PayoutState.AwaitingPayment}-selectAllCheckbox" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( $"{PayoutState.AwaitingPayment}-actions" ) ) . Click ( ) ;
2021-08-05 07:47:25 +02:00
s . Driver . FindElement ( By . Id ( $"{PayoutState.AwaitingPayment}-mark-paid" ) ) . Click ( ) ;
2021-07-16 09:57:37 +02:00
s . FindAlertMessage ( ) ;
2021-10-29 11:01:16 +02:00
2021-10-18 05:37:59 +02:00
s . Driver . FindElement ( By . Id ( $"{PayoutState.InProgress}-view" ) ) . Click ( ) ;
2021-07-16 09:57:37 +02:00
Assert . Contains ( tx . ToString ( ) , s . Driver . PageSource ) ;
2021-11-26 07:02:30 +01:00
2021-10-18 05:37:59 +02:00
//lightning tests
2021-11-26 07:02:30 +01:00
// Since the merchant is sending on lightning, it needs some liquidity from the client
var payoutAmount = LightMoney . Satoshis ( 1000 ) ;
var minimumReserve = LightMoney . Satoshis ( 167773 m ) ;
var inv = await s . Server . MerchantLnd . Client . CreateInvoice ( minimumReserve + payoutAmount , "Donation to merchant" , TimeSpan . FromHours ( 1 ) , default ) ;
var resp = await s . Server . CustomerLightningD . Pay ( inv . BOLT11 ) ;
Assert . Equal ( PayResult . Ok , resp . Result ) ;
2021-10-18 05:37:59 +02:00
newStore = s . CreateNewStore ( ) ;
2021-12-31 14:02:53 +01:00
s . AddLightningNode ( ) ;
2021-10-29 08:25:43 +02:00
//Currently an onchain wallet is required to use the Lightning payouts feature..
2021-10-18 05:37:59 +02:00
s . GenerateWallet ( "BTC" , "" , true , true ) ;
2021-10-22 04:17:40 +02:00
s . GoToStore ( newStore . storeId , StoreNavPages . PullPayments ) ;
2021-10-29 11:01:16 +02:00
2021-10-18 05:37:59 +02:00
s . Driver . FindElement ( By . Id ( "NewPullPayment" ) ) . Click ( ) ;
2021-11-16 04:58:17 +01:00
var paymentMethodOptions = s . Driver . FindElements ( By . CssSelector ( "input[name='PaymentMethods']" ) ) ;
2021-10-18 05:37:59 +02:00
Assert . Equal ( 2 , paymentMethodOptions . Count ) ;
2021-12-31 08:59:02 +01:00
2021-10-18 05:37:59 +02:00
s . Driver . FindElement ( By . Id ( "Name" ) ) . SendKeys ( "Lightning Test" ) ;
s . Driver . FindElement ( By . Id ( "Amount" ) ) . Clear ( ) ;
2021-11-26 07:02:30 +01:00
s . Driver . FindElement ( By . Id ( "Amount" ) ) . SendKeys ( payoutAmount . ToString ( ) ) ;
2021-10-18 05:37:59 +02:00
s . Driver . FindElement ( By . Id ( "Currency" ) ) . Clear ( ) ;
s . Driver . FindElement ( By . Id ( "Currency" ) ) . SendKeys ( "BTC" ) ;
s . Driver . FindElement ( By . Id ( "Create" ) ) . Click ( ) ;
s . Driver . FindElement ( By . LinkText ( "View" ) ) . Click ( ) ;
2021-11-26 07:02:30 +01:00
var bolt = ( await s . Server . CustomerLightningD . CreateInvoice (
payoutAmount ,
2021-12-17 07:31:06 +01:00
$"LN payout test {DateTime.UtcNow.Ticks}" ,
2021-10-18 05:37:59 +02:00
TimeSpan . FromHours ( 1 ) , CancellationToken . None ) ) . BOLT11 ;
s . Driver . FindElement ( By . Id ( "Destination" ) ) . SendKeys ( bolt ) ;
s . Driver . FindElement ( By . Id ( "SelectedPaymentMethod" ) ) . Click ( ) ;
2021-10-29 11:01:16 +02:00
s . Driver . FindElement ( By . CssSelector (
$"#SelectedPaymentMethod option[value={new PaymentMethodId(" BTC ", PaymentTypes.LightningLike)}]" ) )
. Click ( ) ;
2021-10-18 05:37:59 +02:00
s . Driver . FindElement ( By . Id ( "ClaimedAmount" ) ) . SendKeys ( Keys . Enter ) ;
//we do not allow short-life bolts.
s . FindAlertMessage ( StatusMessageModel . StatusSeverity . Error ) ;
2021-11-26 07:02:30 +01:00
bolt = ( await s . Server . CustomerLightningD . CreateInvoice (
payoutAmount ,
2021-12-17 07:31:06 +01:00
$"LN payout test {DateTime.UtcNow.Ticks}" ,
2021-10-18 05:37:59 +02:00
TimeSpan . FromDays ( 31 ) , CancellationToken . None ) ) . BOLT11 ;
s . Driver . FindElement ( By . Id ( "Destination" ) ) . Clear ( ) ;
s . Driver . FindElement ( By . Id ( "Destination" ) ) . SendKeys ( bolt ) ;
s . Driver . FindElement ( By . Id ( "SelectedPaymentMethod" ) ) . Click ( ) ;
2021-10-29 11:01:16 +02:00
s . Driver . FindElement ( By . CssSelector (
$"#SelectedPaymentMethod option[value={new PaymentMethodId(" BTC ", PaymentTypes.LightningLike)}]" ) )
. Click ( ) ;
2021-10-18 05:37:59 +02:00
s . Driver . FindElement ( By . Id ( "ClaimedAmount" ) ) . SendKeys ( Keys . Enter ) ;
s . FindAlertMessage ( ) ;
Assert . Contains ( PayoutState . AwaitingApproval . GetStateString ( ) , s . Driver . PageSource ) ;
2021-10-22 04:17:40 +02:00
s . GoToStore ( newStore . storeId , StoreNavPages . Payouts ) ;
2021-10-29 11:01:16 +02:00
s . Driver . FindElement ( By . Id ( $"{new PaymentMethodId(" BTC ", PaymentTypes.LightningLike)}-view" ) ) . Click ( ) ;
2021-10-18 05:37:59 +02:00
s . Driver . FindElement ( By . Id ( $"{PayoutState.AwaitingApproval}-view" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( $"{PayoutState.AwaitingApproval}-selectAllCheckbox" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( $"{PayoutState.AwaitingApproval}-actions" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( $"{PayoutState.AwaitingApproval}-approve-pay" ) ) . Click ( ) ;
Assert . Contains ( bolt , s . Driver . PageSource ) ;
2021-11-26 07:02:30 +01:00
Assert . Contains ( $"{payoutAmount.ToString()} BTC" , s . Driver . PageSource ) ;
2021-10-18 05:37:59 +02:00
s . Driver . FindElement ( By . CssSelector ( "#pay-invoices-form" ) ) . Submit ( ) ;
2021-11-26 07:02:30 +01:00
s . FindAlertMessage ( StatusMessageModel . StatusSeverity . Success ) ;
2021-10-22 04:17:40 +02:00
s . GoToStore ( newStore . storeId , StoreNavPages . Payouts ) ;
2021-10-29 11:01:16 +02:00
s . Driver . FindElement ( By . Id ( $"{new PaymentMethodId(" BTC ", PaymentTypes.LightningLike)}-view" ) ) . Click ( ) ;
2021-10-18 05:37:59 +02:00
s . Driver . FindElement ( By . Id ( $"{PayoutState.Completed}-view" ) ) . Click ( ) ;
if ( ! s . Driver . PageSource . Contains ( bolt ) )
{
s . Driver . FindElement ( By . Id ( $"{PayoutState.AwaitingPayment}-view" ) ) . Click ( ) ;
Assert . Contains ( bolt , s . Driver . PageSource ) ;
2021-10-29 11:01:16 +02:00
2021-10-18 05:37:59 +02:00
s . Driver . FindElement ( By . Id ( $"{PayoutState.AwaitingPayment}-selectAllCheckbox" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( $"{PayoutState.AwaitingPayment}-actions" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( $"{PayoutState.AwaitingPayment}-mark-paid" ) ) . Click ( ) ;
2021-10-29 11:01:16 +02:00
s . Driver . FindElement ( By . Id ( $"{new PaymentMethodId(" BTC ", PaymentTypes.LightningLike)}-view" ) ) . Click ( ) ;
2021-10-18 05:37:59 +02:00
s . Driver . FindElement ( By . Id ( $"{PayoutState.Completed}-view" ) ) . Click ( ) ;
Assert . Contains ( bolt , s . Driver . PageSource ) ;
}
2021-10-26 13:55:13 +02:00
}
2021-10-29 10:27:33 +02:00
[Fact]
[Trait("Selenium", "Selenium")]
[Trait("Lightning", "Lightning")]
public async Task CanUsePOSPrint ( )
{
2021-11-22 09:16:08 +01:00
using var s = CreateSeleniumTester ( ) ;
2021-10-29 10:27:33 +02:00
s . Server . ActivateLightning ( ) ;
await s . StartAsync ( ) ;
await s . Server . EnsureChannelsSetup ( ) ;
s . RegisterNewUser ( true ) ;
2021-12-31 14:02:53 +01:00
s . CreateNewStore ( ) ;
2022-01-20 12:52:31 +01:00
s . GoToStore ( ) ;
2021-12-31 14:02:53 +01:00
s . AddLightningNode ( LightningConnectionType . CLightning , false ) ;
s . GoToLightningSettings ( ) ;
2021-10-29 10:27:33 +02:00
s . Driver . SetCheckbox ( By . Id ( "LNURLEnabled" ) , true ) ;
2021-12-11 04:32:23 +01:00
s . Driver . FindElement ( By . Id ( "StoreNav-CreateApp" ) ) . Click ( ) ;
2021-10-29 10:27:33 +02:00
s . Driver . FindElement ( By . Id ( "SelectedAppType" ) ) . Click ( ) ;
s . Driver . FindElement ( By . CssSelector ( "option[value='PointOfSale']" ) ) . Click ( ) ;
2021-10-29 16:09:19 +02:00
s . Driver . FindElement ( By . Id ( "AppName" ) ) . SendKeys ( Guid . NewGuid ( ) . ToString ( ) ) ;
2021-10-29 10:27:33 +02:00
s . Driver . FindElement ( By . Id ( "Create" ) ) . Click ( ) ;
2021-12-31 14:02:53 +01:00
TestUtils . Eventually ( ( ) = > Assert . Contains ( "App successfully created" , s . FindAlertMessage ( ) . Text ) ) ;
2021-10-29 10:27:33 +02:00
s . Driver . FindElement ( By . Id ( "DefaultView" ) ) . Click ( ) ;
s . Driver . FindElement ( By . CssSelector ( "option[value='3']" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "SaveSettings" ) ) . Click ( ) ;
2021-12-11 04:32:23 +01:00
Assert . Contains ( "App updated" , s . FindAlertMessage ( ) . Text ) ;
2021-10-29 10:27:33 +02:00
s . Driver . FindElement ( By . Id ( "ViewApp" ) ) . Click ( ) ;
var btns = s . Driver . FindElements ( By . ClassName ( "lnurl" ) ) ;
foreach ( IWebElement webElement in btns )
{
var choice = webElement . GetAttribute ( "data-choice" ) ;
var lnurl = webElement . GetAttribute ( "href" ) ;
var parsed = LNURL . LNURL . Parse ( lnurl , out _ ) ;
2021-10-29 14:51:41 +02:00
Assert . EndsWith ( choice , parsed . ToString ( ) ) ;
2021-10-29 10:27:33 +02:00
Assert . IsType < LNURLPayRequest > ( await LNURL . LNURL . FetchInformation ( parsed , new HttpClient ( ) ) ) ;
}
}
2021-10-29 08:25:43 +02:00
[Fact]
2021-10-26 13:55:13 +02:00
[Trait("Selenium", "Selenium")]
[Trait("Lightning", "Lightning")]
public async Task CanUseLNURL ( )
{
2021-11-22 09:16:08 +01:00
using var s = CreateSeleniumTester ( ) ;
2021-10-26 13:55:13 +02:00
s . Server . ActivateLightning ( ) ;
await s . StartAsync ( ) ;
await s . Server . EnsureChannelsSetup ( ) ;
2021-10-29 08:25:43 +02:00
var cryptoCode = "BTC" ;
await Lightning . Tests . ConnectChannels . ConnectAll ( s . Server . ExplorerNode ,
2021-10-26 13:55:13 +02:00
new [ ] { s . Server . MerchantLightningD } ,
new [ ] { s . Server . MerchantLnd . Client } ) ;
s . RegisterNewUser ( true ) ;
2021-12-31 08:36:38 +01:00
( _ , string storeId ) = s . CreateNewStore ( ) ;
2021-10-29 08:25:43 +02:00
var network = s . Server . NetworkProvider . GetNetwork < BTCPayNetwork > ( cryptoCode ) . NBitcoinNetwork ;
2021-12-31 14:02:53 +01:00
s . AddLightningNode ( LightningConnectionType . CLightning , false ) ;
s . GoToLightningSettings ( ) ;
2022-01-25 04:17:39 +01:00
// LNURL is true by default
Assert . True ( s . Driver . FindElement ( By . Id ( "LNURLEnabled" ) ) . Selected ) ;
2021-10-29 08:25:43 +02:00
// Topup Invoice test
2021-12-31 08:36:38 +01:00
var i = s . CreateInvoice ( storeId , null , cryptoCode ) ;
2021-10-26 13:55:13 +02:00
s . GoToInvoiceCheckout ( i ) ;
s . Driver . FindElement ( By . Id ( "copy-tab" ) ) . Click ( ) ;
var lnurl = s . Driver . FindElement ( By . CssSelector ( "input.checkoutTextbox" ) ) . GetAttribute ( "value" ) ;
var parsed = LNURL . LNURL . Parse ( lnurl , out var tag ) ;
2021-10-29 11:01:16 +02:00
var fetchedReuqest =
Assert . IsType < LNURL . LNURLPayRequest > ( await LNURL . LNURL . FetchInformation ( parsed , new HttpClient ( ) ) ) ;
2021-10-26 13:55:13 +02:00
Assert . Equal ( 1 m , fetchedReuqest . MinSendable . ToDecimal ( LightMoneyUnit . Satoshi ) ) ;
Assert . NotEqual ( 1 m , fetchedReuqest . MaxSendable . ToDecimal ( LightMoneyUnit . Satoshi ) ) ;
var lnurlResponse = await fetchedReuqest . SendRequest ( new LightMoney ( 0.000001 m , LightMoneyUnit . BTC ) ,
network , new HttpClient ( ) ) ;
2021-10-29 11:01:16 +02:00
Assert . Equal ( new LightMoney ( 0.000001 m , LightMoneyUnit . BTC ) ,
lnurlResponse . GetPaymentRequest ( network ) . MinimumAmount ) ;
2021-10-26 13:55:13 +02:00
var lnurlResponse2 = await fetchedReuqest . SendRequest ( new LightMoney ( 0.000002 m , LightMoneyUnit . BTC ) ,
network , new HttpClient ( ) ) ;
Assert . Equal ( new LightMoney ( 0.000002 m , LightMoneyUnit . BTC ) , lnurlResponse2 . GetPaymentRequest ( network ) . MinimumAmount ) ;
2021-10-29 08:25:43 +02:00
await Assert . ThrowsAnyAsync < LightningRPCException > ( async ( ) = >
2021-10-26 13:55:13 +02:00
{
2021-10-29 08:25:43 +02:00
// Initial bolt was cancelled
2021-10-26 13:55:13 +02:00
await s . Server . CustomerLightningD . Pay ( lnurlResponse . Pr ) ;
} ) ;
2021-12-31 08:59:02 +01:00
2021-10-29 08:25:43 +02:00
await s . Server . CustomerLightningD . Pay ( lnurlResponse2 . Pr ) ;
2021-10-26 13:55:13 +02:00
await TestUtils . EventuallyAsync ( async ( ) = >
{
var inv = await s . Server . PayTester . InvoiceRepository . GetInvoice ( i ) ;
Assert . Equal ( InvoiceStatusLegacy . Complete , inv . Status ) ;
} ) ;
2021-10-29 08:25:43 +02:00
// Standard invoice test
2021-12-31 08:36:38 +01:00
s . GoToStore ( storeId ) ;
2022-01-25 04:17:39 +01:00
s . GoToLightningSettings ( ) ;
s . Driver . SetCheckbox ( By . Id ( "LNURLStandardInvoiceEnabled" ) , true ) ;
SudoForceSaveLightningSettingsRightNowAndFast ( s , cryptoCode ) ;
2021-12-31 08:36:38 +01:00
i = s . CreateInvoice ( storeId , 0.0000001 m , cryptoCode ) ;
2021-10-26 13:55:13 +02:00
s . GoToInvoiceCheckout ( i ) ;
s . Driver . FindElement ( By . ClassName ( "payment__currencies" ) ) . Click ( ) ;
2021-10-29 08:25:43 +02:00
// BOLT11 is also available for standard invoices
2021-10-26 13:55:13 +02:00
Assert . Equal ( 2 , s . Driver . FindElements ( By . CssSelector ( ".vex.vex-theme-btcpay .vex-content .vexmenu li.vexmenuitem" ) ) . Count ) ;
s . Driver . FindElement ( By . CssSelector ( ".vex.vex-theme-btcpay .vex-content .vexmenu li.vexmenuitem" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "copy-tab" ) ) . Click ( ) ;
lnurl = s . Driver . FindElement ( By . CssSelector ( "input.checkoutTextbox" ) ) . GetAttribute ( "value" ) ;
parsed = LNURL . LNURL . Parse ( lnurl , out tag ) ;
2021-10-29 08:25:43 +02:00
fetchedReuqest = Assert . IsType < LNURLPayRequest > ( await LNURL . LNURL . FetchInformation ( parsed , new HttpClient ( ) ) ) ;
2021-10-26 13:55:13 +02:00
Assert . Equal ( 0.0000001 m , fetchedReuqest . MaxSendable . ToDecimal ( LightMoneyUnit . BTC ) ) ;
Assert . Equal ( 0.0000001 m , fetchedReuqest . MinSendable . ToDecimal ( LightMoneyUnit . BTC ) ) ;
await Assert . ThrowsAsync < HttpRequestException > ( async ( ) = >
{
await fetchedReuqest . SendRequest ( new LightMoney ( 0.0000002 m , LightMoneyUnit . BTC ) ,
network , new HttpClient ( ) ) ;
} ) ;
await Assert . ThrowsAsync < HttpRequestException > ( async ( ) = >
{
await fetchedReuqest . SendRequest ( new LightMoney ( 0.00000005 m , LightMoneyUnit . BTC ) ,
network , new HttpClient ( ) ) ;
} ) ;
2021-10-29 11:01:16 +02:00
2021-10-26 13:55:13 +02:00
lnurlResponse = await fetchedReuqest . SendRequest ( new LightMoney ( 0.0000001 m , LightMoneyUnit . BTC ) ,
network , new HttpClient ( ) ) ;
lnurlResponse2 = await fetchedReuqest . SendRequest ( new LightMoney ( 0.0000001 m , LightMoneyUnit . BTC ) ,
network , new HttpClient ( ) ) ;
2021-10-29 11:01:16 +02:00
//invoice amounts do no change so the paymnet request is not regenerated
Assert . Equal ( lnurlResponse . Pr , lnurlResponse2 . Pr ) ;
2021-10-26 13:55:13 +02:00
await s . Server . CustomerLightningD . Pay ( lnurlResponse . Pr ) ;
2021-10-29 11:01:16 +02:00
Assert . Equal ( new LightMoney ( 0.0000001 m , LightMoneyUnit . BTC ) ,
lnurlResponse2 . GetPaymentRequest ( network ) . MinimumAmount ) ;
2021-12-31 14:02:53 +01:00
s . GoToHome ( ) ;
s . GoToLightningSettings ( ) ;
2021-10-29 08:25:43 +02:00
// LNURL is enabled and settings are expanded
Assert . True ( s . Driver . FindElement ( By . Id ( "LNURLEnabled" ) ) . Selected ) ;
Assert . Contains ( "show" , s . Driver . FindElement ( By . Id ( "LNURLSettings" ) ) . GetAttribute ( "class" ) ) ;
s . Driver . SetCheckbox ( By . Id ( "LNURLStandardInvoiceEnabled" ) , false ) ;
s . Driver . FindElement ( By . Id ( "save" ) ) . Click ( ) ;
Assert . Contains ( $"{cryptoCode} Lightning settings successfully updated" , s . FindAlertMessage ( ) . Text ) ;
2021-12-31 08:59:02 +01:00
2021-12-31 08:36:38 +01:00
i = s . CreateInvoice ( storeId , 0.000001 m , cryptoCode ) ;
2021-10-26 13:55:13 +02:00
s . GoToInvoiceCheckout ( i ) ;
s . Driver . FindElement ( By . ClassName ( "payment__currencies_noborder" ) ) ;
2021-12-31 08:36:38 +01:00
s . GoToStore ( storeId ) ;
i = s . CreateInvoice ( storeId , null , cryptoCode ) ;
2021-10-26 13:55:13 +02:00
s . GoToInvoiceCheckout ( i ) ;
s . Driver . FindElement ( By . ClassName ( "payment__currencies_noborder" ) ) ;
2021-10-29 11:01:16 +02:00
2021-12-31 14:02:53 +01:00
s . GoToHome ( ) ;
s . GoToLightningSettings ( ) ;
2021-10-29 08:25:43 +02:00
s . Driver . SetCheckbox ( By . Id ( "LNURLBech32Mode" ) , false ) ;
2021-10-29 11:01:16 +02:00
s . Driver . SetCheckbox ( By . Id ( "LNURLStandardInvoiceEnabled" ) , false ) ;
2021-10-29 08:25:43 +02:00
s . Driver . SetCheckbox ( By . Id ( "DisableBolt11PaymentMethod" ) , true ) ;
s . Driver . FindElement ( By . Id ( "save" ) ) . Click ( ) ;
Assert . Contains ( $"{cryptoCode} Lightning settings successfully updated" , s . FindAlertMessage ( ) . Text ) ;
2021-12-31 08:59:02 +01:00
2021-10-29 08:25:43 +02:00
// Ensure the toggles are set correctly
2021-12-31 14:02:53 +01:00
s . GoToLightningSettings ( ) ;
2021-10-29 16:09:19 +02:00
//TODO: DisableBolt11PaymentMethod is actually disabled because LNURLStandardInvoiceEnabled is disabled
// checkboxes is not good choice here, in next release we should have multi choice instead
2021-10-29 08:25:43 +02:00
Assert . False ( s . Driver . FindElement ( By . Id ( "LNURLBech32Mode" ) ) . Selected ) ;
2021-11-26 07:02:30 +01:00
Assert . False ( s . Driver . FindElement ( By . Id ( "LNURLStandardInvoiceEnabled" ) ) . Selected ) ;
2021-12-31 08:59:02 +01:00
2021-11-26 07:02:30 +01:00
//even though we set DisableBolt11PaymentMethod to true, logic when saving it turns it back off as otherwise no lightning option is available at all!
Assert . False ( s . Driver . FindElement ( By . Id ( "DisableBolt11PaymentMethod" ) ) . Selected ) ;
// Invoice creation should fail, because it is a standard invoice with amount, but DisableBolt11PaymentMethod = true and LNURLStandardInvoiceEnabled = false
2021-12-31 08:59:02 +01:00
s . CreateInvoice ( storeId , 0.0000001 m , cryptoCode , "" , null , expectedSeverity : StatusMessageModel . StatusSeverity . Success ) ;
2021-10-29 08:25:43 +02:00
2021-12-31 08:36:38 +01:00
i = s . CreateInvoice ( storeId , null , cryptoCode ) ;
2021-10-26 13:55:13 +02:00
s . GoToInvoiceCheckout ( i ) ;
s . Driver . FindElement ( By . ClassName ( "payment__currencies_noborder" ) ) ;
s . Driver . FindElement ( By . Id ( "copy-tab" ) ) . Click ( ) ;
lnurl = s . Driver . FindElement ( By . CssSelector ( "input.checkoutTextbox" ) ) . GetAttribute ( "value" ) ;
Assert . StartsWith ( "lnurlp" , lnurl ) ;
2021-10-29 08:25:43 +02:00
LNURL . LNURL . Parse ( lnurl , out tag ) ;
2021-12-31 08:59:02 +01:00
2021-10-26 13:55:13 +02:00
s . GoToHome ( ) ;
2021-12-31 14:02:53 +01:00
s . CreateNewStore ( false ) ;
s . AddLightningNode ( LightningConnectionType . LndREST , false ) ;
s . GoToLightningSettings ( ) ;
2021-10-29 08:25:43 +02:00
s . Driver . SetCheckbox ( By . Id ( "LNURLEnabled" ) , true ) ;
s . Driver . SetCheckbox ( By . Id ( "DisableBolt11PaymentMethod" ) , true ) ;
2022-01-25 04:17:39 +01:00
s . Driver . SetCheckbox ( By . Id ( "LNURLStandardInvoiceEnabled" ) , true ) ;
2021-10-29 08:25:43 +02:00
s . Driver . FindElement ( By . Id ( "save" ) ) . Click ( ) ;
Assert . Contains ( $"{cryptoCode} Lightning settings successfully updated" , s . FindAlertMessage ( ) . Text ) ;
2021-12-31 14:02:53 +01:00
var invForPP = s . CreateInvoice ( 0.0000001 m , cryptoCode ) ;
2021-10-26 13:55:13 +02:00
s . GoToInvoiceCheckout ( invForPP ) ;
s . Driver . FindElement ( By . Id ( "copy-tab" ) ) . Click ( ) ;
lnurl = s . Driver . FindElement ( By . CssSelector ( "input.checkoutTextbox" ) ) . GetAttribute ( "value" ) ;
parsed = LNURL . LNURL . Parse ( lnurl , out tag ) ;
2021-12-31 08:59:02 +01:00
2021-10-29 08:25:43 +02:00
// Check that pull payment has lightning option
2021-10-26 13:55:13 +02:00
s . GoToStore ( s . StoreId , StoreNavPages . PullPayments ) ;
s . Driver . FindElement ( By . Id ( "NewPullPayment" ) ) . Click ( ) ;
2021-12-31 08:59:02 +01:00
Assert . Equal ( new PaymentMethodId ( cryptoCode , PaymentTypes . LightningLike ) , PaymentMethodId . Parse ( Assert . Single ( s . Driver . FindElements ( By . CssSelector ( "input[name='PaymentMethods']" ) ) ) . GetAttribute ( "value" ) ) ) ;
2021-10-26 13:55:13 +02:00
s . Driver . FindElement ( By . Id ( "Name" ) ) . SendKeys ( "PP1" ) ;
s . Driver . FindElement ( By . Id ( "Amount" ) ) . Clear ( ) ;
2021-10-29 11:01:16 +02:00
s . Driver . FindElement ( By . Id ( "Amount" ) ) . SendKeys ( "0.0000001" ) ;
2021-10-26 13:55:13 +02:00
s . Driver . FindElement ( By . Id ( "Create" ) ) . Click ( ) ;
s . Driver . FindElement ( By . LinkText ( "View" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "Destination" ) ) . SendKeys ( lnurl ) ;
2021-10-29 11:01:16 +02:00
2021-10-26 13:55:13 +02:00
var pullPaymentId = s . Driver . Url . Split ( '/' ) . Last ( ) ;
s . Driver . FindElement ( By . Id ( "ClaimedAmount" ) ) . Clear ( ) ;
s . Driver . FindElement ( By . Id ( "ClaimedAmount" ) ) . SendKeys ( "0.0000001" + Keys . Enter ) ;
s . FindAlertMessage ( ) ;
2021-12-31 08:59:02 +01:00
2021-10-26 13:55:13 +02:00
s . GoToStore ( s . StoreId , StoreNavPages . PullPayments ) ;
var payouts = s . Driver . FindElements ( By . ClassName ( "pp-payout" ) ) ;
payouts [ 0 ] . Click ( ) ;
2021-10-29 11:01:16 +02:00
s . Driver . FindElement ( By . Id ( "BTC_LightningLike-view" ) ) . Click ( ) ;
2021-10-26 13:55:13 +02:00
Assert . NotEmpty ( s . Driver . FindElements ( By . ClassName ( "payout" ) ) ) ;
s . Driver . FindElement ( By . Id ( $"{PayoutState.AwaitingApproval}-selectAllCheckbox" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( $"{PayoutState.AwaitingApproval}-actions" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( $"{PayoutState.AwaitingApproval}-approve-pay" ) ) . Click ( ) ;
Assert . Contains ( lnurl , s . Driver . PageSource ) ;
2021-10-29 11:01:16 +02:00
2021-10-26 13:55:13 +02:00
s . Driver . FindElement ( By . Id ( "pay-invoices-form" ) ) . Submit ( ) ;
2021-10-29 11:01:16 +02:00
2021-10-26 13:55:13 +02:00
await TestUtils . EventuallyAsync ( async ( ) = >
{
var inv = await s . Server . PayTester . InvoiceRepository . GetInvoice ( invForPP ) ;
Assert . Equal ( InvoiceStatusLegacy . Complete , inv . Status ) ;
await using var ctx = s . Server . PayTester . GetService < ApplicationDbContextFactory > ( ) . CreateContext ( ) ;
var payoutsData = await ctx . Payouts . Where ( p = > p . PullPaymentDataId = = pullPaymentId ) . ToListAsync ( ) ;
Assert . True ( payoutsData . All ( p = > p . State = = PayoutState . Completed ) ) ;
} ) ;
2021-12-14 04:12:51 +01:00
//lnurl crowdfund support
s . GoToStore ( ) ;
s . Driver . FindElement ( By . Id ( "StoreNav-CreateApp" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Name ( "AppName" ) ) . SendKeys ( "CF" + Guid . NewGuid ( ) ) ;
s . Driver . FindElement ( By . Id ( "SelectedAppType" ) ) . SendKeys ( "Crowdfund" ) ;
s . Driver . FindElement ( By . Id ( "Create" ) ) . Click ( ) ;
2022-02-07 10:37:45 +01:00
Assert . Contains ( "App successfully created" , s . FindAlertMessage ( ) . Text ) ;
2021-12-14 04:12:51 +01:00
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 ( "SaveSettings" ) ) . Click ( ) ;
2022-02-07 10:37:45 +01:00
Assert . Contains ( "App updated" , s . FindAlertMessage ( ) . Text ) ;
2021-12-14 04:12:51 +01:00
s . Driver . FindElement ( By . Id ( "ViewApp" ) ) . Click ( ) ;
2022-02-07 10:37:45 +01:00
var windows = s . Driver . WindowHandles ;
Assert . Equal ( 2 , windows . Count ) ;
s . Driver . SwitchTo ( ) . Window ( windows [ 1 ] ) ;
2021-12-14 04:12:51 +01:00
s . Driver . FindElement ( By . CssSelector ( "#crowdfund-body-contribution-container .perk" ) ) . Click ( ) ;
s . Driver . FindElement ( By . PartialLinkText ( "LNURL" ) ) . Click ( ) ;
lnurl = s . Driver . FindElement ( By . ClassName ( "lnurl" ) )
. GetAttribute ( "href" ) ;
LNURL . LNURL . Parse ( lnurl , out tag ) ;
2022-02-07 10:37:45 +01:00
s . Driver . Close ( ) ;
s . Driver . SwitchTo ( ) . Window ( windows [ 0 ] ) ;
2020-06-24 03:34:09 +02:00
}
2021-01-22 17:49:26 +01:00
2021-10-29 11:01:16 +02:00
[Fact]
[Trait("Selenium", "Selenium")]
[Trait("Lightning", "Lightning")]
public async Task CanUseLNAddress ( )
{
2021-11-22 09:16:08 +01:00
using var s = CreateSeleniumTester ( ) ;
2021-10-29 11:01:16 +02:00
s . Server . ActivateLightning ( ) ;
await s . StartAsync ( ) ;
await s . Server . EnsureChannelsSetup ( ) ;
s . RegisterNewUser ( true ) ;
//ln address tests
2021-11-11 06:30:19 +01:00
s . CreateNewStore ( ) ;
2021-11-10 10:50:39 +01:00
//ensure ln address is not available as Lightning is not enable
2021-12-31 08:36:38 +01:00
s . Driver . AssertElementNotFound ( By . Id ( "StoreNav-LightningAddress" ) ) ;
2021-10-29 11:01:16 +02:00
2021-12-31 14:02:53 +01:00
s . AddLightningNode ( LightningConnectionType . LndREST , false ) ;
2021-12-31 08:59:02 +01:00
2021-12-31 08:36:38 +01:00
s . Driver . FindElement ( By . Id ( "StoreNav-LightningAddress" ) ) . Click ( ) ;
2021-10-29 11:01:16 +02:00
s . Driver . ToggleCollapse ( "AddAddress" ) ;
var lnaddress1 = Guid . NewGuid ( ) . ToString ( ) ;
s . Driver . FindElement ( By . Id ( "Add_Username" ) ) . SendKeys ( lnaddress1 ) ;
s . Driver . FindElement ( By . CssSelector ( "button[value='add']" ) ) . Click ( ) ;
s . FindAlertMessage ( StatusMessageModel . StatusSeverity . Success ) ;
s . Driver . ToggleCollapse ( "AddAddress" ) ;
s . Driver . FindElement ( By . Id ( "Add_Username" ) ) . SendKeys ( lnaddress1 ) ;
s . Driver . FindElement ( By . CssSelector ( "button[value='add']" ) ) . Click ( ) ;
s . Driver . FindElement ( By . ClassName ( "text-danger" ) ) ;
s . Driver . FindElement ( By . Id ( "Add_Username" ) ) . Clear ( ) ;
var lnaddress2 = "EUR" + Guid . NewGuid ( ) . ToString ( ) ;
s . Driver . FindElement ( By . Id ( "Add_Username" ) ) . SendKeys ( lnaddress2 ) ;
s . Driver . ToggleCollapse ( "AdvancedSettings" ) ;
s . Driver . FindElement ( By . Id ( "Add_CurrencyCode" ) ) . SendKeys ( "EUR" ) ;
s . Driver . FindElement ( By . Id ( "Add_Min" ) ) . SendKeys ( "2" ) ;
s . Driver . FindElement ( By . Id ( "Add_Max" ) ) . SendKeys ( "10" ) ;
s . Driver . FindElement ( By . CssSelector ( "button[value='add']" ) ) . Click ( ) ;
s . FindAlertMessage ( StatusMessageModel . StatusSeverity . Success ) ;
var addresses = s . Driver . FindElements ( By . ClassName ( "lightning-address-value" ) ) ;
Assert . Equal ( 2 , addresses . Count ) ;
foreach ( IWebElement webElement in addresses )
{
var value = webElement . GetAttribute ( "value" ) ;
//cannot test this directly as https is not supported on our e2e tests
// var request = await LNURL.LNURL.FetchPayRequestViaInternetIdentifier(value, new HttpClient());
var lnurl = new Uri ( LNURL . LNURL . ExtractUriFromInternetIdentifier ( value ) . ToString ( )
. Replace ( "https" , "http" ) ) ;
2021-12-31 08:59:02 +01:00
var request = ( LNURL . LNURLPayRequest ) await LNURL . LNURL . FetchInformation ( lnurl , new HttpClient ( ) ) ;
2021-10-29 11:01:16 +02:00
switch ( value )
{
case { } v when v . StartsWith ( lnaddress2 ) :
Assert . Equal ( 2 , request . MinSendable . ToDecimal ( LightMoneyUnit . Satoshi ) ) ;
Assert . Equal ( 10 , request . MaxSendable . ToDecimal ( LightMoneyUnit . Satoshi ) ) ;
break ;
case { } v when v . StartsWith ( lnaddress1 ) :
Assert . Equal ( 1 , request . MinSendable . ToDecimal ( LightMoneyUnit . Satoshi ) ) ;
Assert . Equal ( 6.12 m , request . MaxSendable . ToDecimal ( LightMoneyUnit . BTC ) ) ;
break ;
}
}
}
2021-12-24 09:27:00 +01:00
[Fact]
[Trait("Selenium", "Selenium")]
public async Task CanSigninWithLoginCode ( )
{
using var s = CreateSeleniumTester ( ) ;
await s . StartAsync ( ) ;
var user = s . RegisterNewUser ( ) ;
s . GoToProfile ( ManageNavPages . LoginCodes ) ;
var code = s . Driver . FindElement ( By . Id ( "logincode" ) ) . GetAttribute ( "value" ) ;
s . Driver . FindElement ( By . Id ( "regeneratecode" ) ) . Click ( ) ;
Assert . NotEqual ( code , s . Driver . FindElement ( By . Id ( "logincode" ) ) . GetAttribute ( "value" ) ) ;
2021-12-31 08:59:02 +01:00
2021-12-24 09:27:00 +01:00
code = s . Driver . FindElement ( By . Id ( "logincode" ) ) . GetAttribute ( "value" ) ;
s . Logout ( ) ;
s . GoToLogin ( ) ;
s . Driver . SetAttribute ( "LoginCode" , "value" , "bad code" ) ;
s . Driver . InvokeJSFunction ( "logincode-form" , "submit" ) ;
2021-12-31 08:59:02 +01:00
2021-12-24 09:27:00 +01:00
s . Driver . SetAttribute ( "LoginCode" , "value" , code ) ;
s . Driver . InvokeJSFunction ( "logincode-form" , "submit" ) ;
s . GoToProfile ( ) ;
Assert . Contains ( user , s . Driver . PageSource ) ;
}
2021-12-31 08:59:02 +01:00
2021-11-26 07:07:54 +01:00
// For god know why, selenium have problems clicking on the save button, resulting in ultimate hacks
// to make it works.
private void SudoForceSaveLightningSettingsRightNowAndFast ( SeleniumTester s , string cryptoCode )
{
int maxAttempts = 5 ;
2021-11-27 03:40:06 +01:00
retry :
2021-11-26 07:07:54 +01:00
s . Driver . WaitForAndClick ( By . Id ( "save" ) ) ;
try
{
Assert . Contains ( $"{cryptoCode} Lightning settings successfully updated" , s . FindAlertMessage ( ) . Text ) ;
}
catch ( NoSuchElementException ) when ( maxAttempts > 0 )
{
maxAttempts - - ;
goto retry ;
}
}
2021-11-11 13:03:08 +01:00
[Fact]
[Trait("Selenium", "Selenium")]
public async Task CanUseLNURLAuth ( )
{
using var s = CreateSeleniumTester ( ) ;
await s . StartAsync ( ) ;
var user = s . RegisterNewUser ( true ) ;
s . GoToProfile ( ManageNavPages . TwoFactorAuthentication ) ;
s . Driver . FindElement ( By . Name ( "Name" ) ) . SendKeys ( "ln wallet" ) ;
s . Driver . FindElement ( By . Name ( "type" ) )
. FindElement ( By . CssSelector ( $"option[value='{(int)Fido2Credential.CredentialType.LNURLAuth}']" ) ) . Click ( ) ;
s . Driver . FindElement ( By . Id ( "btn-add" ) ) . Click ( ) ;
var links = s . Driver . FindElements ( By . CssSelector ( ".tab-content a" ) ) . Select ( element = > element . GetAttribute ( "href" ) ) ;
Assert . Equal ( 2 , links . Count ( ) ) ;
Uri prevEndpoint = null ;
foreach ( string link in links )
{
var endpoint = LNURL . LNURL . Parse ( link , out var tag ) ;
Assert . Equal ( "login" , tag ) ;
if ( endpoint . Scheme ! = "https" )
prevEndpoint = endpoint ;
}
var linkingKey = new Key ( ) ;
var request = Assert . IsType < LNAuthRequest > ( await LNURL . LNURL . FetchInformation ( prevEndpoint , null ) ) ;
_ = await request . SendChallenge ( linkingKey , new HttpClient ( ) ) ;
TestUtils . Eventually ( ( ) = > s . FindAlertMessage ( ) ) ;
s . Logout ( ) ;
s . Login ( user , "123456" ) ;
var section = s . Driver . FindElement ( By . Id ( "lnurlauth-section" ) ) ;
links = section . FindElements ( By . CssSelector ( ".tab-content a" ) ) . Select ( element = > element . GetAttribute ( "href" ) ) ;
Assert . Equal ( 2 , links . Count ( ) ) ;
prevEndpoint = null ;
foreach ( string link in links )
{
var endpoint = LNURL . LNURL . Parse ( link , out var tag ) ;
Assert . Equal ( "login" , tag ) ;
if ( endpoint . Scheme ! = "https" )
prevEndpoint = endpoint ;
}
request = Assert . IsType < LNAuthRequest > ( await LNURL . LNURL . FetchInformation ( prevEndpoint , null ) ) ;
_ = await request . SendChallenge ( linkingKey , new HttpClient ( ) ) ;
TestUtils . Eventually ( ( ) = >
{
Assert . Equal ( s . Driver . Url , s . ServerUri . ToString ( ) ) ;
} ) ;
}
2021-01-22 17:49:26 +01:00
private static void CanBrowseContent ( SeleniumTester s )
{
s . Driver . FindElement ( By . ClassName ( "delivery-content" ) ) . Click ( ) ;
var windows = s . Driver . WindowHandles ;
Assert . Equal ( 2 , windows . Count ) ;
s . Driver . SwitchTo ( ) . Window ( windows [ 1 ] ) ;
JObject . Parse ( s . Driver . FindElement ( By . TagName ( "body" ) ) . Text ) ;
s . Driver . Close ( ) ;
s . Driver . SwitchTo ( ) . Window ( windows [ 0 ] ) ;
}
private static void CanSetupEmailCore ( SeleniumTester s )
{
2021-05-19 04:39:27 +02:00
s . Driver . FindElement ( By . Id ( "QuickFillDropdownToggle" ) ) . Click ( ) ;
2021-12-11 04:32:23 +01:00
s . Driver . FindElement ( By . CssSelector ( "#quick-fill .dropdown-menu .dropdown-item:first-child" ) ) . Click ( ) ;
2021-01-22 17:49:26 +01:00
s . Driver . FindElement ( By . Id ( "Settings_Login" ) ) . SendKeys ( "test@gmail.com" ) ;
s . Driver . FindElement ( By . CssSelector ( "button[value=\"Save\"]" ) ) . Submit ( ) ;
s . FindAlertMessage ( ) ;
s . Driver . FindElement ( By . Id ( "Settings_Password" ) ) . SendKeys ( "mypassword" ) ;
2022-01-18 02:19:27 +01:00
s . Driver . FindElement ( By . Id ( "Save" ) ) . SendKeys ( Keys . Enter ) ;
2021-01-22 17:49:26 +01:00
Assert . Contains ( "Configured" , s . Driver . PageSource ) ;
s . Driver . FindElement ( By . Id ( "Settings_Login" ) ) . SendKeys ( "test_fix@gmail.com" ) ;
2022-01-18 02:19:27 +01:00
s . Driver . FindElement ( By . Id ( "Save" ) ) . SendKeys ( Keys . Enter ) ;
2021-01-22 17:49:26 +01:00
Assert . Contains ( "Configured" , s . Driver . PageSource ) ;
Assert . Contains ( "test_fix" , s . Driver . PageSource ) ;
2022-01-18 02:19:27 +01:00
s . Driver . FindElement ( By . Id ( "ResetPassword" ) ) . SendKeys ( Keys . Enter ) ;
2021-01-22 17:49:26 +01:00
s . FindAlertMessage ( ) ;
Assert . DoesNotContain ( "Configured" , s . Driver . PageSource ) ;
Assert . Contains ( "test_fix" , s . Driver . PageSource ) ;
}
private static string AssertUrlHasPairingCode ( SeleniumTester s )
{
var regex = Regex . Match ( new Uri ( s . Driver . Url , UriKind . Absolute ) . Query , "pairingCode=([^&]*)" ) ;
Assert . True ( regex . Success , $"{s.Driver.Url} does not match expected regex" ) ;
var pairingCode = regex . Groups [ 1 ] . Value ;
return pairingCode ;
}
private void SetTransactionOutput ( SeleniumTester s , int index , BitcoinAddress dest , decimal amount , bool subtract = false )
{
s . Driver . FindElement ( By . Id ( $"Outputs_{index}__DestinationAddress" ) ) . SendKeys ( dest . ToString ( ) ) ;
var amountElement = s . Driver . FindElement ( By . Id ( $"Outputs_{index}__Amount" ) ) ;
amountElement . Clear ( ) ;
amountElement . SendKeys ( amount . ToString ( CultureInfo . InvariantCulture ) ) ;
var checkboxElement = s . Driver . FindElement ( By . Id ( $"Outputs_{index}__SubtractFeesFromOutput" ) ) ;
if ( checkboxElement . Selected ! = subtract )
{
checkboxElement . Click ( ) ;
}
}
2019-05-12 10:13:26 +02:00
}
}