(Refactor) : Converted Selenium test for CanUseLndSeedBackup , CanUseLNURLAuth and Others to playwright (#6852)

* (Test):Converted/Added Playwright Test for CanUseLndSeedBackup

Signed-off-by: Abhijay jain <Abhijay007j@gmail.com>

* (Refactor): Removed Selenium Test for CanUseLndSeedBackup

Signed-off-by: Abhijay jain <Abhijay007j@gmail.com>

* (Refactor): Resovled merge conflicts

Signed-off-by: Abhijay jain <Abhijay007j@gmail.com>

* (Refactor): Removed Selenium Test for CanUseLNURLAuth

Signed-off-by: Abhijay jain <Abhijay007j@gmail.com>

* (Test):Converted/Added Playwright Test for CanUseCoinSelectionFilters

Signed-off-by: Abhijay jain <Abhijay007j@gmail.com>

* (Refactor): Removed Selenium Test for CanUseCoinSelectionFilters

Signed-off-by: Abhijay jain <Abhijay007j@gmail.com>

* (Test):Converted/Added Playwright Test for CanManageLightningNode

Signed-off-by: Abhijay jain <Abhijay007j@gmail.com>

* (Refactor): Removed Selenium Test for CanManageLightningNode

Signed-off-by: Abhijay jain <Abhijay007j@gmail.com>

* (Test):Converted/Added Playwright Test for CanEditPullPaymentUI

Signed-off-by: Abhijay jain <Abhijay007j@gmail.com>

* (Refactor): Removed Selenium Test for CanEditPullPaymentUI

Signed-off-by: Abhijay jain <Abhijay007j@gmail.com>

* (Test):Converted/Added Playwright Test for CookieReflectProperPermissions

Signed-off-by: Abhijay jain <Abhijay007j@gmail.com>

* (Refactor): Removed Selenium Test for CookieReflectProperPermissions

Signed-off-by: Abhijay jain <Abhijay007j@gmail.com>

---------

Signed-off-by: Abhijay jain <Abhijay007j@gmail.com>
This commit is contained in:
Abhijay Jain
2025-07-17 16:05:31 +05:30
committed by GitHub
parent cd42f1a53d
commit 03c5f4bb3c
2 changed files with 375 additions and 350 deletions

View File

@@ -3,11 +3,14 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using BTCPayServer.Abstractions.Models;
using BTCPayServer.Client;
using BTCPayServer.Client.Models;
using BTCPayServer.Data;
using BTCPayServer.Events;
using BTCPayServer.Lightning;
using BTCPayServer.Payments;
using BTCPayServer.Services;
using BTCPayServer.Services.Invoices;
@@ -18,6 +21,7 @@ using BTCPayServer.Views.Stores;
using BTCPayServer.Views.Wallets;
using Dapper;
using ExchangeSharp;
using LNURL;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Playwright;
@@ -1563,6 +1567,377 @@ namespace BTCPayServer.Tests
await s.Page.WaitForSelectorAsync("#WalletTransactions[data-loaded='true']");
Assert.Contains("There are no transactions yet", await s.Page.Locator("#WalletTransactions").TextContentAsync());
}
[Fact]
[Trait("Lightning", "Lightning")]
public async Task CanUseLndSeedBackup()
{
await using var s = CreatePlaywrightTester();
s.Server.ActivateLightning();
await s.StartAsync();
await s.RegisterNewUser(true);
await s.GoToHome();
await s.GoToServer(ServerNavPages.Services);
await s.Page.AssertNoError();
s.TestLogs.LogInformation("Let's see if we can access LND's seed");
Assert.Contains("server/services/lndseedbackup/BTC", await s.Page.ContentAsync());
await s.GoToUrl("/server/services/lndseedbackup/BTC");
await s.Page.ClickAsync("#details");
var seedEl = s.Page.Locator("#Seed");
await Expect(seedEl).ToBeVisibleAsync();
Assert.Contains("about over million", await seedEl.GetAttributeAsync("value"), StringComparison.OrdinalIgnoreCase);
var passEl = s.Page.Locator("#WalletPassword");
await Expect(passEl).ToBeVisibleAsync();
Assert.Contains(await passEl.TextContentAsync(), "hellorockstar", StringComparison.OrdinalIgnoreCase);
await s.Page.ClickAsync("#delete");
await s.Page.WaitForSelectorAsync("#ConfirmInput");
await s.Page.FillAsync("#ConfirmInput", "DELETE");
await s.Page.ClickAsync("#ConfirmContinue");
await s.FindAlertMessage();
seedEl = s.Page.Locator("#Seed");
Assert.Contains("Seed removed", await seedEl.TextContentAsync(), StringComparison.OrdinalIgnoreCase);
}
[Fact]
public async Task CanUseLNURLAuth()
{
await using var s = CreatePlaywrightTester();
await s.StartAsync();
var user = await s.RegisterNewUser(true);
await s.GoToHome();
await s.GoToProfile(ManageNavPages.TwoFactorAuthentication);
await s.Page.FillAsync("[name='Name']", "ln wallet");
await s.Page.SelectOptionAsync("[name='type']", $"{(int)Fido2Credential.CredentialType.LNURLAuth}");
await s.Page.ClickAsync("#btn-add");
var linkElements = await s.Page.Locator(".tab-content a").AllAsync();
var links = new List<string>();
foreach (var element in linkElements)
{
var href = await element.GetAttributeAsync("href");
if (href != null) links.Add(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());
await TestUtils.EventuallyAsync(async () => await s.FindAlertMessage());
await s.CreateNewStore(); // create a store to prevent redirect after login
await s.Logout();
await s.LogIn(user, "123456");
var section = s.Page.Locator("#lnurlauth-section");
linkElements = await section.Locator(".tab-content a").AllAsync();
links = new List<string>();
foreach (var element in linkElements)
{
var href = await element.GetAttributeAsync("href");
if (href != null) links.Add(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());
await TestUtils.EventuallyAsync(() =>
{
Assert.StartsWith(s.ServerUri.ToString(), s.Page.Url);
return Task.CompletedTask;
});
}
[Fact]
public async Task CanUseCoinSelectionFilters()
{
await using var s = CreatePlaywrightTester();
await s.StartAsync();
await s.RegisterNewUser(true);
(_, string storeId) = await s.CreateNewStore();
await s.GenerateWallet("BTC", "", false, true);
var walletId = new WalletId(storeId, "BTC");
await s.GoToWallet(walletId, WalletsNavPages.Receive);
var addressStr = await s.Page.GetAttributeAsync("#Address", "data-text");
var address = BitcoinAddress.Create(addressStr,
((BTCPayNetwork)s.Server.NetworkProvider.GetNetwork("BTC")).NBitcoinNetwork);
await s.Server.ExplorerNode.GenerateAsync(1);
const decimal AmountTiny = 0.001m;
const decimal AmountSmall = 0.005m;
const decimal AmountMedium = 0.009m;
const decimal AmountLarge = 0.02m;
List<uint256> txs =
[
await s.Server.ExplorerNode.SendToAddressAsync(address, Money.Coins(AmountTiny)),
await s.Server.ExplorerNode.SendToAddressAsync(address, Money.Coins(AmountSmall)),
await s.Server.ExplorerNode.SendToAddressAsync(address, Money.Coins(AmountMedium)),
await s.Server.ExplorerNode.SendToAddressAsync(address, Money.Coins(AmountLarge))
];
await s.Server.ExplorerNode.GenerateAsync(1);
await s.GoToWallet(walletId);
await s.Page.ClickAsync("#toggleInputSelection");
var input = s.Page.Locator("input[placeholder^='Filter']");
await input.WaitForAsync();
Assert.NotNull(input);
// Test amountmin
await input.ClearAsync();
await input.FillAsync("amountmin:0.01");
await TestUtils.EventuallyAsync(async () => {
Assert.Single(await s.Page.Locator("li.list-group-item").AllAsync());
});
// Test amountmax
await input.ClearAsync();
await input.FillAsync("amountmax:0.002");
await TestUtils.EventuallyAsync(async () => {
Assert.Single(await s.Page.Locator("li.list-group-item").AllAsync());
});
// Test general text (txid)
await input.ClearAsync();
await input.FillAsync(txs[2].ToString()[..8]);
await TestUtils.EventuallyAsync(async () => {
Assert.Single(await s.Page.Locator("li.list-group-item").AllAsync());
});
// Test timestamp before/after
await input.ClearAsync();
await input.FillAsync("after:2099-01-01");
await TestUtils.EventuallyAsync(async () => {
Assert.Empty(await s.Page.Locator("li.list-group-item").AllAsync());
});
await input.ClearAsync();
await input.FillAsync("before:2099-01-01");
await TestUtils.EventuallyAsync(async () =>
{
Assert.True((await s.Page.Locator("li.list-group-item").AllAsync()).Count >= 4);
});
}
[Fact]
[Trait("Playwright", "Playwright")]
[Trait("Lightning", "Lightning")]
public async Task CanManageLightningNode()
{
await using var s = CreatePlaywrightTester();
s.Server.ActivateLightning();
await s.StartAsync();
await s.Server.EnsureChannelsSetup();
await s.RegisterNewUser(true);
(string storeName, _) = await s.CreateNewStore();
// Check status in navigation
await s.Page.Locator("#StoreNav-LightningBTC .btcpay-status--pending").WaitForAsync();
// Set up LN node
await s.AddLightningNode();
await s.Page.Locator("#StoreNav-LightningBTC .btcpay-status--enabled").WaitForAsync();
// Check public node info for availability
var opening = s.Page.Context.WaitForPageAsync();
await s.Page.ClickAsync("#PublicNodeInfo");
var newPage = await opening;
await Expect(newPage.Locator(".store-name")).ToHaveTextAsync(storeName);
await Expect(newPage.Locator("#LightningNodeTitle")).ToHaveTextAsync("BTC Lightning Node");
await Expect(newPage.Locator("#LightningNodeStatus")).ToHaveTextAsync("Online");
await newPage.Locator(".btcpay-status--enabled").WaitForAsync();
await newPage.Locator("#LightningNodeUrlClearnet").WaitForAsync();
await newPage.CloseAsync();
// Set wrong node connection string to simulate offline node
await s.GoToLightningSettings();
await s.Page.ClickAsync("#SetupLightningNodeLink");
await s.Page.ClickAsync("label[for=\"LightningNodeType-Custom\"]");
await s.Page.Locator("#ConnectionString").WaitForAsync();
await s.Page.Locator("#ConnectionString").ClearAsync();
await s.Page.FillAsync("#ConnectionString", "type=lnd-rest;server=https://doesnotwork:8080/");
await s.Page.ClickAsync("#test");
await s.FindAlertMessage(StatusMessageModel.StatusSeverity.Error);
await s.ClickPagePrimary();
await s.FindAlertMessage(partialText: "BTC Lightning node updated.");
// Check offline state is communicated in nav item
await s.Page.Locator("#StoreNav-LightningBTC .btcpay-status--disabled").WaitForAsync();
// Check public node info for availability
opening = s.Page.Context.WaitForPageAsync();
await s.Page.ClickAsync("#PublicNodeInfo");
newPage = await opening;
await Expect(newPage.Locator(".store-name")).ToHaveTextAsync(storeName);
await Expect(newPage.Locator("#LightningNodeTitle")).ToHaveTextAsync("BTC Lightning Node");
await Expect(newPage.Locator("#LightningNodeStatus")).ToHaveTextAsync("Unavailable");
await newPage.Locator(".btcpay-status--disabled").WaitForAsync();
await Expect(newPage.Locator("#LightningNodeUrlClearnet")).ToBeHiddenAsync();
}
[Fact]
[Trait("Playwright", "Playwright")]
[Trait("Lightning", "Lightning")]
public async Task CanEditPullPaymentUI()
{
await using var s = CreatePlaywrightTester();
s.Server.ActivateLightning(LightningConnectionType.LndREST);
await s.StartAsync();
await s.Server.EnsureChannelsSetup();
await s.RegisterNewUser(true);
await s.CreateNewStore();
await s.GenerateWallet("BTC", "", true, true);
await s.Server.ExplorerNode.GenerateAsync(1);
await s.FundStoreWallet(denomination: 50.0m);
await s.GoToStore(s.StoreId, StoreNavPages.PullPayments);
await s.ClickPagePrimary();
await s.Page.FillAsync("#Name", "PP1");
await s.Page.Locator("#Amount").ClearAsync();
await s.Page.FillAsync("#Amount", "99.0");
await s.ClickPagePrimary();
var opening = s.Page.Context.WaitForPageAsync();
await s.Page.ClickAsync("text=View");
var newPage = await opening;
await Expect(newPage.Locator("body")).ToContainTextAsync("PP1");
await newPage.CloseAsync();
await s.GoToStore(s.StoreId, StoreNavPages.PullPayments);
await s.Page.ClickAsync("text=PP1");
var name = s.Page.Locator("#Name");
await name.ClearAsync();
await name.FillAsync("PP1 Edited");
var description = s.Page.Locator(".card-block");
await description.FillAsync("Description Edit");
await s.ClickPagePrimary();
opening = s.Page.Context.WaitForPageAsync();
await s.Page.ClickAsync("text=View");
newPage = await opening;
await Expect(newPage.Locator("body")).ToContainTextAsync("Description Edit");
await Expect(newPage.Locator("body")).ToContainTextAsync("PP1 Edited");
}
[Fact]
public async Task CookieReflectProperPermissions()
{
await using var s = CreatePlaywrightTester();
await s.StartAsync();
var alice = s.Server.NewAccount();
alice.Register(false);
await alice.CreateStoreAsync();
var bob = s.Server.NewAccount();
await bob.CreateStoreAsync();
await bob.AddGuest(alice.UserId);
await s.GoToLogin();
await s.LogIn(alice.Email, alice.Password);
await s.GoToUrl($"/cheat/permissions/stores/{bob.StoreId}");
var pageSource = await s.Page.ContentAsync();
AssertPermissions(pageSource, true,
new[]
{
Policies.CanViewInvoices,
Policies.CanModifyInvoices,
Policies.CanViewPaymentRequests,
Policies.CanViewPullPayments,
Policies.CanViewPayouts,
Policies.CanModifyStoreSettingsUnscoped,
Policies.CanDeleteUser
});
AssertPermissions(pageSource, false,
new[]
{
Policies.CanModifyStoreSettings,
Policies.CanCreateNonApprovedPullPayments,
Policies.CanCreatePullPayments,
Policies.CanManagePullPayments,
Policies.CanModifyServerSettings
});
await s.GoToUrl($"/cheat/permissions/stores/{alice.StoreId}");
pageSource = await s.Page.ContentAsync();
AssertPermissions(pageSource, true,
new[]
{
Policies.CanViewInvoices,
Policies.CanModifyInvoices,
Policies.CanViewPaymentRequests,
Policies.CanViewStoreSettings,
Policies.CanModifyStoreSettingsUnscoped,
Policies.CanDeleteUser,
Policies.CanModifyStoreSettings,
Policies.CanCreateNonApprovedPullPayments,
Policies.CanCreatePullPayments,
Policies.CanManagePullPayments,
Policies.CanArchivePullPayments,
});
AssertPermissions(pageSource, false,
new[]
{
Policies.CanModifyServerSettings
});
await s.GoToUrl("/logout");
await alice.MakeAdmin();
await s.GoToLogin();
await s.LogIn(alice.Email, alice.Password);
await s.GoToUrl($"/cheat/permissions/stores/{alice.StoreId}");
pageSource = await s.Page.ContentAsync();
AssertPermissions(pageSource, true,
new[]
{
Policies.CanViewInvoices,
Policies.CanModifyInvoices,
Policies.CanViewPaymentRequests,
Policies.CanViewStoreSettings,
Policies.CanModifyStoreSettingsUnscoped,
Policies.CanDeleteUser,
Policies.CanModifyStoreSettings,
Policies.CanCreateNonApprovedPullPayments,
Policies.CanCreatePullPayments,
Policies.CanManagePullPayments,
Policies.CanModifyServerSettings,
Policies.CanCreateUser,
Policies.CanManageUsers
});
}
void AssertPermissions(string source, bool expected, string[] permissions)
{
if (expected)
{
foreach (var p in permissions)
Assert.Contains(p + "<", source);
}
else
{
foreach (var p in permissions)
Assert.DoesNotContain(p + "<", source);
}
}
}
}

View File

@@ -51,37 +51,6 @@ namespace BTCPayServer.Tests
{
}
[Fact(Timeout = TestTimeout)]
[Trait("Lightning", "Lightning")]
public async Task CanUseLndSeedBackup()
{
using var s = CreateSeleniumTester();
s.Server.ActivateLightning();
await s.StartAsync();
s.RegisterNewUser(true);
s.GoToHome();
s.GoToServer(ServerNavPages.Services);
s.Driver.AssertNoError();
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.GetAttribute("value"), 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);
}
[Fact(Timeout = TestTimeout)]
public async Task CanUseInvoiceReceipts()
{
@@ -371,107 +340,7 @@ namespace BTCPayServer.Tests
AssertUrlHasPairingCode(s);
}
[Fact(Timeout = TestTimeout)]
public async Task CookieReflectProperPermissions()
{
using var s = CreateSeleniumTester();
await s.StartAsync();
var alice = s.Server.NewAccount();
alice.Register(false);
await alice.CreateStoreAsync();
var bob = s.Server.NewAccount();
await bob.CreateStoreAsync();
await bob.AddGuest(alice.UserId);
s.GoToLogin();
s.LogIn(alice.Email, alice.Password);
s.GoToUrl($"/cheat/permissions/stores/{bob.StoreId}");
var pageSource = s.Driver.PageSource;
AssertPermissions(pageSource, true,
new[]
{
Policies.CanViewInvoices,
Policies.CanModifyInvoices,
Policies.CanViewPaymentRequests,
Policies.CanViewPullPayments,
Policies.CanViewPayouts,
Policies.CanModifyStoreSettingsUnscoped,
Policies.CanDeleteUser
});
AssertPermissions(pageSource, false,
new[]
{
Policies.CanModifyStoreSettings,
Policies.CanCreateNonApprovedPullPayments,
Policies.CanCreatePullPayments,
Policies.CanManagePullPayments,
Policies.CanModifyServerSettings
});
s.GoToUrl($"/cheat/permissions/stores/{alice.StoreId}");
pageSource = s.Driver.PageSource;
AssertPermissions(pageSource, true,
new[]
{
Policies.CanViewInvoices,
Policies.CanModifyInvoices,
Policies.CanViewPaymentRequests,
Policies.CanViewStoreSettings,
Policies.CanModifyStoreSettingsUnscoped,
Policies.CanDeleteUser,
Policies.CanModifyStoreSettings,
Policies.CanCreateNonApprovedPullPayments,
Policies.CanCreatePullPayments,
Policies.CanManagePullPayments,
Policies.CanArchivePullPayments,
});
AssertPermissions(pageSource, false,
new[]
{
Policies.CanModifyServerSettings
});
s.GoToUrl("/logout");
await alice.MakeAdmin();
s.GoToLogin();
s.LogIn(alice.Email, alice.Password);
s.GoToUrl($"/cheat/permissions/stores/{alice.StoreId}");
pageSource = s.Driver.PageSource;
AssertPermissions(pageSource, true,
new[]
{
Policies.CanViewInvoices,
Policies.CanModifyInvoices,
Policies.CanViewPaymentRequests,
Policies.CanViewStoreSettings,
Policies.CanModifyStoreSettingsUnscoped,
Policies.CanDeleteUser,
Policies.CanModifyStoreSettings,
Policies.CanCreateNonApprovedPullPayments,
Policies.CanCreatePullPayments,
Policies.CanManagePullPayments,
Policies.CanModifyServerSettings,
Policies.CanCreateUser,
Policies.CanManageUsers
});
}
void AssertPermissions(string source, bool expected, string[] permissions)
{
if (expected)
{
foreach (var p in permissions)
Assert.Contains(p + "<", source);
}
else
{
foreach (var p in permissions)
Assert.DoesNotContain(p + "<", source);
}
}
[Fact(Timeout = TestTimeout)]
public async Task CanCreateAppPoS()
@@ -952,79 +821,6 @@ namespace BTCPayServer.Tests
Assert.Equal(spentOutpoint, tx.Inputs[0].PrevOut);
}
[Fact(Timeout = TestTimeout)]
public async Task CanUseCoinSelectionFilters()
{
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);
var addressStr = s.Driver.FindElement(By.Id("Address")).GetAttribute("data-text");
var address = BitcoinAddress.Create(addressStr,
((BTCPayNetwork)s.Server.NetworkProvider.GetNetwork("BTC")).NBitcoinNetwork);
await s.Server.ExplorerNode.GenerateAsync(1);
const decimal AmountTiny = 0.001m;
const decimal AmountSmall = 0.005m;
const decimal AmountMedium = 0.009m;
const decimal AmountLarge = 0.02m;
List<uint256> txs =
[
await s.Server.ExplorerNode.SendToAddressAsync(address, Money.Coins(AmountTiny)),
await s.Server.ExplorerNode.SendToAddressAsync(address, Money.Coins(AmountSmall)),
await s.Server.ExplorerNode.SendToAddressAsync(address, Money.Coins(AmountMedium)),
await s.Server.ExplorerNode.SendToAddressAsync(address, Money.Coins(AmountLarge))
];
await s.Server.ExplorerNode.GenerateAsync(1);
s.GoToWallet(walletId);
s.Driver.WaitForAndClick(By.Id("toggleInputSelection"));
var input = s.Driver.WaitForElement(By.CssSelector("input[placeholder^='Filter']"));
Assert.NotNull(input);
// Test amountmin
input.Clear();
input.SendKeys("amountmin:0.01");
TestUtils.Eventually(() => {
Assert.Single(s.Driver.FindElements(By.CssSelector("li.list-group-item")));
});
// Test amountmax
input.Clear();
input.SendKeys("amountmax:0.002");
TestUtils.Eventually(() => {
Assert.Single(s.Driver.FindElements(By.CssSelector("li.list-group-item")));
});
// Test general text (txid)
input.Clear();
input.SendKeys(txs[2].ToString()[..8]);
TestUtils.Eventually(() => {
Assert.Single(s.Driver.FindElements(By.CssSelector("li.list-group-item")));
});
// Test timestamp before/after
input.Clear();
input.SendKeys("after:2099-01-01");
TestUtils.Eventually(() => {
Assert.Empty(s.Driver.FindElements(By.CssSelector("li.list-group-item")));
});
input.Clear();
input.SendKeys("before:2099-01-01");
TestUtils.Eventually(() =>
{
Assert.True(s.Driver.FindElements(By.CssSelector("li.list-group-item")).Count >= 4);
});
}
[Fact(Timeout = TestTimeout)]
public async Task CanUseWebhooks()
{
@@ -1138,104 +934,9 @@ namespace BTCPayServer.Tests
[Fact]
[Trait("Selenium", "Selenium")]
[Trait("Lightning", "Lightning")]
public async Task CanManageLightningNode()
{
using var s = CreateSeleniumTester();
s.Server.ActivateLightning();
await s.StartAsync();
await s.Server.EnsureChannelsSetup();
s.RegisterNewUser(true);
(string storeName, _) = s.CreateNewStore();
// Check status in navigation
s.Driver.FindElement(By.CssSelector("#StoreNav-LightningBTC .btcpay-status--pending"));
// Set up LN node
s.AddLightningNode();
s.Driver.FindElement(By.CssSelector("#StoreNav-LightningBTC .btcpay-status--enabled"));
// Check public node info for availability
s.Driver.FindElement(By.Id("PublicNodeInfo")).Click();
s.Driver.SwitchTo().Window(s.Driver.WindowHandles.Last());
Assert.Equal(storeName, s.Driver.FindElement(By.CssSelector(".store-name")).Text);
Assert.Equal("BTC Lightning Node", s.Driver.FindElement(By.Id("LightningNodeTitle")).Text);
Assert.Equal("Online", s.Driver.FindElement(By.Id("LightningNodeStatus")).Text);
s.Driver.FindElement(By.CssSelector(".btcpay-status--enabled"));
s.Driver.FindElement(By.Id("LightningNodeUrlClearnet"));
s.Driver.Close();
s.Driver.SwitchTo().Window(s.Driver.WindowHandles.First());
// Set wrong node connection string to simulate offline node
s.GoToLightningSettings();
s.Driver.FindElement(By.Id("SetupLightningNodeLink")).Click();
s.Driver.FindElement(By.CssSelector("label[for=\"LightningNodeType-Custom\"]")).Click();
s.Driver.WaitForElement(By.Id("ConnectionString")).Clear();
s.Driver.FindElement(By.Id("ConnectionString")).SendKeys("type=lnd-rest;server=https://doesnotwork:8080/");
s.Driver.FindElement(By.Id("test")).Click();
Assert.Contains("Error", s.FindAlertMessage(StatusMessageModel.StatusSeverity.Error).Text);
s.ClickPagePrimary();
Assert.Contains("BTC Lightning node updated.", s.FindAlertMessage().Text);
// Check offline state is communicated in nav item
s.Driver.FindElement(By.CssSelector("#StoreNav-LightningBTC .btcpay-status--disabled"));
// Check public node info for availability
s.Driver.FindElement(By.Id("PublicNodeInfo")).Click();
s.Driver.SwitchTo().Window(s.Driver.WindowHandles.Last());
Assert.Equal(storeName, s.Driver.FindElement(By.CssSelector(".store-name")).Text);
Assert.Equal("BTC Lightning Node", s.Driver.FindElement(By.Id("LightningNodeTitle")).Text);
Assert.Equal("Unavailable", s.Driver.FindElement(By.Id("LightningNodeStatus")).Text);
s.Driver.FindElement(By.CssSelector(".btcpay-status--disabled"));
s.Driver.AssertElementNotFound(By.Id("LightningNodeUrlClearnet"));
}
[Fact]
[Trait("Selenium", "Selenium")]
[Trait("Lightning", "Lightning")]
public async Task CanEditPullPaymentUI()
{
using var s = CreateSeleniumTester();
s.Server.ActivateLightning(LightningConnectionType.LndREST);
await s.StartAsync();
await s.Server.EnsureChannelsSetup();
s.RegisterNewUser(true);
s.CreateNewStore();
s.GenerateWallet("BTC", "", true, true);
await s.Server.ExplorerNode.GenerateAsync(1);
await s.FundStoreWallet(denomination: 50.0m);
s.GoToStore(s.StoreId, StoreNavPages.PullPayments);
s.ClickPagePrimary();
s.Driver.FindElement(By.Id("Name")).SendKeys("PP1");
s.Driver.FindElement(By.Id("Amount")).Clear();
s.Driver.FindElement(By.Id("Amount")).SendKeys("99.0");
s.ClickPagePrimary();
s.Driver.FindElement(By.LinkText("View")).Click();
s.Driver.SwitchTo().Window(s.Driver.WindowHandles.Last());
Assert.Contains("PP1", s.Driver.PageSource);
s.Driver.Close();
s.Driver.SwitchTo().Window(s.Driver.WindowHandles.First());
s.GoToStore(s.StoreId, StoreNavPages.PullPayments);
s.Driver.FindElement(By.LinkText("PP1")).Click();
var name = s.Driver.FindElement(By.Id("Name"));
name.Clear();
name.SendKeys("PP1 Edited");
var description = s.Driver.FindElement(By.ClassName("card-block"));
description.SendKeys("Description Edit");
s.ClickPagePrimary();
s.Driver.FindElement(By.LinkText("View")).Click();
s.Driver.SwitchTo().Window(s.Driver.WindowHandles.Last());
Assert.Contains("Description Edit", s.Driver.PageSource);
Assert.Contains("PP1 Edited", s.Driver.PageSource);
}
[Fact]
[Trait("Selenium", "Selenium")]
@@ -2145,57 +1846,6 @@ retry:
}
}
[Fact]
[Trait("Selenium", "Selenium")]
public async Task CanUseLNURLAuth()
{
using var s = CreateSeleniumTester();
await s.StartAsync();
var user = s.RegisterNewUser(true);
s.GoToHome();
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.CreateNewStore(); // create a store to prevent redirect after login
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")).ToList();
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.StartsWith(s.ServerUri.ToString(), s.Driver.Url);
});
}
[Fact]
[Trait("Selenium", "Selenium")]
public async Task CanUseRoleManager()