This commit is contained in:
Kukks 2021-05-18 12:26:07 +02:00
parent fb71fcbaac
commit 6b86b46911
2 changed files with 93 additions and 103 deletions

View file

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Threading.Tasks; using System.Threading.Tasks;
using BTCPayServer.Abstractions.Models; using BTCPayServer.Abstractions.Models;
@ -14,6 +15,7 @@ using BTCPayServer.Views.Wallets;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using NBitcoin; using NBitcoin;
using BTCPayServer.BIP78.Sender; using BTCPayServer.BIP78.Sender;
using OpenQA.Selenium;
using PlaywrightSharp; using PlaywrightSharp;
using PlaywrightSharp.Chromium; using PlaywrightSharp.Chromium;
using Xunit; using Xunit;
@ -77,7 +79,7 @@ namespace BTCPayServer.Tests
Logs.Tester.LogInformation($"Selenium: Browsing to {Server.PayTester.ServerUri}"); Logs.Tester.LogInformation($"Selenium: Browsing to {Server.PayTester.ServerUri}");
Logs.Tester.LogInformation($"Selenium: Resolution {Page.ViewportSize}"); Logs.Tester.LogInformation($"Selenium: Resolution {Page.ViewportSize}");
await GoToRegister(); await GoToRegister();
Page.AssertNoError(); await Page.AssertNoError();
} }
public IChromiumBrowserContext Context { get; set; } public IChromiumBrowserContext Context { get; set; }
@ -115,7 +117,7 @@ namespace BTCPayServer.Tests
if (isAdmin) if (isAdmin)
await Page.CheckAsync("#IsAdmin"); await Page.CheckAsync("#IsAdmin");
await Page.ClickAsync("#RegisterButton"); await Page.ClickAsync("#RegisterButton");
Page.AssertNoError(); await Page.AssertNoError();
return usr; return usr;
} }
@ -124,78 +126,78 @@ namespace BTCPayServer.Tests
await Page.ClickAsync( "#Stores"); await Page.ClickAsync( "#Stores");
await Page.ClickAsync("#CreateStore"); await Page.ClickAsync("#CreateStore");
var name = "Store" + RandomUtils.GetUInt64(); var name = "Store" + RandomUtils.GetUInt64();
Page.WaitForElement("#Name")).SendKeys(name); await Page.TypeAsync("#Name", name);
Page.WaitForElement("#Create")).Click(); await Page.ClickAsync("#Create");
StoreId = Page.WaitForElement("#Id")).GetAttribute("value"); StoreId = await (await Page.QuerySelectorAsync("#Id")).GetAttributeAsync("value");
return (name, StoreId); return (name, StoreId);
} }
public Mnemonic GenerateWallet(string cryptoCode = "BTC", string seed = "", bool importkeys = false, bool privkeys = false, ScriptPubKeyType format = ScriptPubKeyType.Segwit) public async Task<Mnemonic> GenerateWallet(string cryptoCode = "BTC", string seed = "", bool importkeys = false, bool privkeys = false, ScriptPubKeyType format = ScriptPubKeyType.Segwit)
{ {
Page.FindElement(By.Id($"Modify{cryptoCode}")).Click(); await Page.ClickAsync($"#Modify{cryptoCode}");
// Replace previous wallet case // Replace previous wallet case
if (Page.PageSource.Contains("id=\"ChangeWalletLink\"")) if ((await Page.GetContentAsync()).Contains("id=\"ChangeWalletLink\""))
{ {
Page.FindElement("#ChangeWalletLink")).Click(); await Page.ClickAsync("#ChangeWalletLink");
Page.FindElement("#continue")).Click(); await Page.ClickAsync("#continue");
} }
if (string.IsNullOrEmpty(seed)) if (string.IsNullOrEmpty(seed))
{ {
var option = privkeys ? "Hotwallet" : "Watchonly"; var option = privkeys ? "Hotwallet" : "Watchonly";
Logs.Tester.LogInformation($"Generating new seed ({option})"); Logs.Tester.LogInformation($"Generating new seed ({option})");
Page.FindElement("#GenerateWalletLink")).Click(); await Page.ClickAsync("#GenerateWalletLink");
Page.FindElement(By.Id($"Generate{option}Link")).Click(); await Page.ClickAsync($"#Generate{option}Link");
} }
else else
{ {
Logs.Tester.LogInformation("Progressing with existing seed"); Logs.Tester.LogInformation("Progressing with existing seed");
Page.FindElement("#ImportWalletOptionsLink")).Click(); await Page.ClickAsync("#ImportWalletOptionsLink");
Page.FindElement("#ImportSeedLink")).Click(); await Page.ClickAsync("#ImportSeedLink");
Page.FindElement("#ExistingMnemonic")).SendKeys(seed); await Page.TypeAsync("#ExistingMnemonic", seed);
Page.SetCheckbox("#SavePrivateKeys"), privkeys); await Page.SetCheckbox("#SavePrivateKeys", privkeys);
} }
Page.FindElement("#ScriptPubKeyType")).Click(); await Page.ClickAsync("#ScriptPubKeyType");
Page.FindElement(By.CssSelector($"#ScriptPubKeyType option[value={format}]")).Click(); await Page.ClickAsync($"#ScriptPubKeyType option[value={format}]");
// Open advanced settings via JS, because if we click the link it triggers the toggle animation. // Open advanced settings via JS, because if we click the link it triggers the toggle animation.
// This leads to Selenium trying to click the button while it is moving resulting in an error. // This leads to Selenium trying to click the button while it is moving resulting in an error.
Page.ExecuteJavaScript("document.getElementById('AdvancedSettings').classList.add('show')"); await Page.EvaluateAsync("document.getElementById('AdvancedSettings').classList.add('show')");
Page.SetCheckbox("#ImportKeysToRPC"), importkeys); await Page.SetCheckbox("#ImportKeysToRPC", importkeys);
Page.FindElement("#Continue")).Click(); await Page.ClickAsync("#Continue");
// Seed backup page // Seed backup page
FindAlertMessage(); await FindAlertMessage();
if (string.IsNullOrEmpty(seed)) if (string.IsNullOrEmpty(seed))
{ {
seed = Page.FindElements("#RecoveryPhrase")).First().GetAttribute("data-mnemonic"); seed = await (await Page.QuerySelectorAsync("#RecoveryPhrase")).GetAttributeAsync("data-mnemonic");
} }
// Confirm seed backup // Confirm seed backup
Page.FindElement("#confirm")).Click(); await Page.ClickAsync("#confirm");
Page.FindElement("#submit")).Click(); await Page.ClickAsync("#submit");
WalletId = new WalletId(StoreId, cryptoCode); WalletId = new WalletId(StoreId, cryptoCode);
return new Mnemonic(seed); return new Mnemonic(seed);
} }
public void AddDerivationScheme(string cryptoCode = "BTC", string derivationScheme = "xpub661MyMwAqRbcGABgHMUXDzPzH1tU7eZaAaJQXhDXsSxsqyQzQeU6kznNfSuAyqAK9UaWSaZaMFdNiY5BCF4zBPAzSnwfUAwUhwttuAKwfRX-[legacy]") public async Task AddDerivationScheme(string cryptoCode = "BTC", string derivationScheme = "xpub661MyMwAqRbcGABgHMUXDzPzH1tU7eZaAaJQXhDXsSxsqyQzQeU6kznNfSuAyqAK9UaWSaZaMFdNiY5BCF4zBPAzSnwfUAwUhwttuAKwfRX-[legacy]")
{ {
Page.FindElement(By.Id($"Modify{cryptoCode}")).Click(); await Page.ClickAsync($"#Modify{cryptoCode}");
Page.FindElement("#ImportWalletOptionsLink")).Click(); await Page.ClickAsync("#ImportWalletOptionsLink");
Page.FindElement("#ImportXpubLink")).Click(); await Page.ClickAsync("#ImportXpubLink");
Page.FindElement("#DerivationScheme")).SendKeys(derivationScheme); await Page.TypeAsync("#DerivationScheme",derivationScheme);
Page.FindElement("#Continue")).Click(); await Page.ClickAsync("#Continue");
Page.FindElement("#Confirm")).Click(); await Page.ClickAsync("#Confirm");
FindAlertMessage(); await FindAlertMessage();
} }
public void AddLightningNode(string cryptoCode = "BTC", LightningConnectionType? connectionType = null) public async Task AddLightningNode(string cryptoCode = "BTC", LightningConnectionType? connectionType = null)
{ {
Page.FindElement(By.Id($"Modify-Lightning{cryptoCode}")).Click(); await Page.ClickAsync($"#Modify-Lightning{cryptoCode}");
var connectionString = connectionType switch var connectionString = connectionType switch
{ {
@ -210,128 +212,118 @@ namespace BTCPayServer.Tests
if (connectionString == null) if (connectionString == null)
{ {
Assert.True(Page.FindElement("#LightningNodeType-Internal")).Enabled, "Usage of the internal Lightning node is disabled."); Assert.True(await (await Page.QuerySelectorAsync("#LightningNodeType-Internal")).IsEnabledAsync(), "Usage of the internal Lightning node is disabled.");
Page.FindElement(By.CssSelector("label[for=\"LightningNodeType-Internal\"]")).Click(); await Page.ClickAsync("label[for=\"LightningNodeType-Internal\"]");
} }
else else
{ {
Page.FindElement(By.CssSelector("label[for=\"LightningNodeType-Custom\"]")).Click(); await Page.ClickAsync("label[for=\"LightningNodeType-Custom\"]");
Page.FindElement("#ConnectionString")).SendKeys(connectionString); await Page.TypeAsync("#ConnectionString", connectionString);
Page.FindElement("#test")).Click(); await Page.ClickAsync("#test");
Assert.Contains("Connection to the Lightning node successful.", FindAlertMessage().Text); Assert.Contains("Connection to the Lightning node successful.", await (await FindAlertMessage()).GetTextContentAsync());
} }
Page.FindElement("#save")).Click(); await Page.ClickAsync("#save");
Assert.Contains($"{cryptoCode} Lightning node updated.", FindAlertMessage().Text); Assert.Contains($"{cryptoCode} Lightning node updated.", await (await FindAlertMessage()).GetTextContentAsync());
var enabled = Page.FindElement(By.Id($"{cryptoCode}LightningEnabled")); var enabled = await Page.QuerySelectorAsync($"#{cryptoCode}LightningEnabled");
if (enabled.Text == "Enable") if (await enabled.GetTextContentAsync() == "Enable")
{ {
enabled.Click(); await enabled.ClickAsync();
Assert.Contains($"{cryptoCode} Lightning payments are now enabled for this store.", FindAlertMessage().Text); Assert.Contains($"{cryptoCode} Lightning payments are now enabled for this store.", await (await FindAlertMessage()).GetTextContentAsync());
} }
} }
public void ClickOnAllSideMenus() public async Task ClickOnAllSideMenus()
{ {
var links = Page.FindElements(By.CssSelector(".nav .nav-link")).Select(c => c.GetAttribute("href")).ToList(); var links = await Task.WhenAll(Page
Page.AssertNoError(); .QuerySelectorAllAsync(".nav .nav-link")
.ContinueWith<string>(c => c.Result.SelectMany<IElementHandle>(handle => handle.GetAttributeAsync("href"))));
await Page.AssertNoError();
Assert.NotEmpty(links); Assert.NotEmpty(links);
foreach (var l in links) foreach (var l in links)
{ {
Logs.Tester.LogInformation($"Checking no error on {l}"); Logs.Tester.LogInformation($"Checking no error on {l}");
Page.Navigate().GoToUrl(l); await Page.GoToAsync(l);
Page.AssertNoError(); await Page.AssertNoError();
} }
} }
public void Dispose() public void Dispose()
{ {
if (Page != null) Page.CloseAsync().GetAwaiter().GetResult();
{ PlayWright.Dispose();
try
{
Page.Quit();
}
catch
{
// ignored
}
Page.Dispose();
}
Server?.Dispose(); Server?.Dispose();
} }
internal void AssertNotFound() internal async Task AssertNotFound()
{ {
Assert.Contains("404 - Page not found</h1>", Page.PageSource); Assert.Contains("404 - Page not found</h1>", await Page.GetContentAsync());
} }
public void GoToHome() public async Task GoToHome()
{ {
Page.Navigate().GoToUrl(Server.PayTester.ServerUri); await Page.GoToAsync(Server.PayTester.ServerUri.ToString());
} }
public void Logout() public async Task Logout()
{ {
Page.FindElement("#Logout")).Click(); await Page.ClickAsync("#Logout");
} }
public void Login(string user, string password) public async Task Login(string user, string password)
{ {
Page.FindElement("#Email")).SendKeys(user); await Page.TypeAsync("#Email", user);
Page.FindElement("#Password")).SendKeys(password); await Page.TypeAsync("#Password",password);
Page.FindElement("#LoginButton")).Click(); await Page.ClickAsync("#LoginButton");
} }
public void GoToStores() public async Task GoToStores()
{ {
Page.FindElement("#Stores")).Click(); await Page.ClickAsync("#Stores");
} }
public void GoToStore(string storeId, StoreNavPages storeNavPage = StoreNavPages.Index) public async Task GoToStore(string storeId, StoreNavPages storeNavPage = StoreNavPages.Index)
{ {
Page.FindElement("#Stores")).Click(); await Page.ClickAsync("#Stores");
Page.FindElement(By.Id($"update-store-{storeId}")).Click(); await Page.ClickAsync($"#update-store-{storeId}");
if (storeNavPage != StoreNavPages.Index) if (storeNavPage != StoreNavPages.Index)
{ {
Page.FindElement(By.Id(storeNavPage.ToString())).Click(); await Page.ClickAsync($"#{storeNavPage}");
} }
} }
public void GoToInvoiceCheckout(string invoiceId) public async Task GoToInvoiceCheckout(string invoiceId)
{ {
Page.FindElement("#Invoices")).Click(); await Page.ClickAsync("#Invoices");
Page.FindElement(By.Id($"invoice-checkout-{invoiceId}")).Click(); await Page.ClickAsync($"#invoice-checkout-{invoiceId}");
CheckForJSErrors(); await CheckForJSErrors();
} }
public void GoToInvoices() public async Task GoToInvoices()
{ {
Page.FindElement("#Invoices")).Click(); await Page.ClickAsync("#Invoices");
} }
public void GoToProfile(ManageNavPages navPages = ManageNavPages.Index) public async Task GoToProfile(ManageNavPages navPages = ManageNavPages.Index)
{ {
Page.FindElement("#MySettings")).Click(); await Page.ClickAsync("#MySettings");
if (navPages != ManageNavPages.Index) if (navPages != ManageNavPages.Index)
{ {
Page.FindElement(By.Id(navPages.ToString())).Click(); await Page.ClickAsync($"#{navPages}");
} }
} }
public void GoToLogin() public async Task GoToLogin()
{ {
Page.Navigate().GoToUrl(new Uri(Server.PayTester.ServerUri, "/login")); await Page.GoToAsync(new Uri(Server.PayTester.ServerUri, "/login").ToString());
} }
public string CreateInvoice(string storeName, decimal amount = 100, string currency = "USD", string refundEmail = "") public async Task<string> CreateInvoice(string storeName, decimal amount = 100, string currency = "USD", string refundEmail = "")
{ {
GoToInvoices(); await GoToInvoices();
Page.FindElement("#CreateNewInvoice")).Click(); Page.FindElement("#CreateNewInvoice")).Click();
Page.FindElement("#Amount")).SendKeys(amount.ToString(CultureInfo.InvariantCulture)); Page.FindElement("#Amount")).SendKeys(amount.ToString(CultureInfo.InvariantCulture));
var currencyEl = Page.FindElement("#Currency")); var currencyEl = Page.FindElement("#Currency"));

View file

@ -137,18 +137,16 @@ namespace BTCPayServer.Tests
wait.UntilJsIsReady(); wait.UntilJsIsReady();
} }
public static void SetCheckbox(this IPage driver, By selector, bool value) public static async Task SetCheckbox(this IPage driver, string selector, bool value)
{ {
var element = driver.FindElement(selector); var element = await driver.QuerySelectorAsync(selector);
if ((value && !element.Selected) || (!value && element.Selected)) if (value)
{ {
driver.WaitForAndClick(selector); await element.CheckAsync();
} }
else
if (value != element.Selected)
{ {
Logs.Tester.LogInformation("SetCheckbox recursion, trying to click again"); await element.UncheckAsync();
driver.SetCheckbox(selector, value);
} }
} }
} }