2022-11-24 00:53:32 +01:00
|
|
|
using System;
|
|
|
|
using System.Threading;
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
using BTCPayServer.Payments;
|
|
|
|
using BTCPayServer.Tests.Logging;
|
|
|
|
using BTCPayServer.Views.Stores;
|
|
|
|
using NBitcoin;
|
|
|
|
using OpenQA.Selenium;
|
2023-03-01 07:49:21 +01:00
|
|
|
using OpenQA.Selenium.Support.UI;
|
2022-11-24 00:53:32 +01:00
|
|
|
using Xunit;
|
|
|
|
using Xunit.Abstractions;
|
|
|
|
|
|
|
|
namespace BTCPayServer.Tests
|
|
|
|
{
|
|
|
|
[Trait("Selenium", "Selenium")]
|
|
|
|
[Collection(nameof(NonParallelizableCollectionDefinition))]
|
|
|
|
public class CheckoutV2Tests : UnitTestBase
|
|
|
|
{
|
|
|
|
private const int TestTimeout = TestUtils.TestTimeout;
|
2023-01-06 14:18:07 +01:00
|
|
|
|
2022-11-24 00:53:32 +01:00
|
|
|
public CheckoutV2Tests(ITestOutputHelper helper) : base(helper)
|
|
|
|
{
|
|
|
|
}
|
2023-01-06 14:18:07 +01:00
|
|
|
|
2022-11-24 00:53:32 +01:00
|
|
|
[Fact(Timeout = TestTimeout)]
|
|
|
|
[Trait("Lightning", "Lightning")]
|
|
|
|
public async Task CanConfigureCheckout()
|
|
|
|
{
|
|
|
|
using var s = CreateSeleniumTester();
|
|
|
|
s.Server.ActivateLightning();
|
|
|
|
await s.StartAsync();
|
|
|
|
s.GoToRegister();
|
|
|
|
s.RegisterNewUser(true);
|
|
|
|
s.CreateNewStore();
|
|
|
|
s.EnableCheckoutV2();
|
|
|
|
s.AddLightningNode();
|
2023-02-10 03:23:48 +01:00
|
|
|
// Use non-legacy derivation scheme
|
|
|
|
s.AddDerivationScheme("BTC", "tpubDD79XF4pzhmPSJ9AyUay9YbXAeD1c6nkUqC32pnKARJH6Ja5hGUfGc76V82ahXpsKqN6UcSGXMkzR34aZq4W23C6DAdZFaVrzWqzj24F8BC");
|
2022-11-24 00:53:32 +01:00
|
|
|
|
|
|
|
// Configure store url
|
|
|
|
var storeUrl = "https://satoshisteaks.com/";
|
|
|
|
s.GoToStore();
|
|
|
|
s.Driver.FindElement(By.Id("StoreWebsite")).SendKeys(storeUrl);
|
|
|
|
s.Driver.FindElement(By.Id("Save")).Click();
|
|
|
|
Assert.Contains("Store successfully updated", s.FindAlertMessage().Text);
|
2023-01-24 10:10:38 +01:00
|
|
|
|
|
|
|
// Enable LNURL, which we will need for (non-)presence checks throughout this test
|
|
|
|
s.GoToHome();
|
|
|
|
s.GoToLightningSettings();
|
|
|
|
s.Driver.SetCheckbox(By.Id("LNURLEnabled"), true);
|
|
|
|
s.Driver.SetCheckbox(By.Id("LNURLStandardInvoiceEnabled"), true);
|
|
|
|
s.Driver.FindElement(By.Id("save")).Click();
|
|
|
|
Assert.Contains("BTC Lightning settings successfully updated", s.FindAlertMessage().Text);
|
|
|
|
|
|
|
|
// Top up/zero amount invoices
|
|
|
|
var invoiceId = s.CreateInvoice(amount: null);
|
2022-11-24 00:53:32 +01:00
|
|
|
s.GoToInvoiceCheckout(invoiceId);
|
2023-01-06 14:18:07 +01:00
|
|
|
|
2022-12-10 11:19:13 +01:00
|
|
|
// Ensure we are seeing Checkout v2
|
|
|
|
s.Driver.WaitUntilAvailable(By.Id("Checkout-v2"));
|
2023-01-24 10:10:38 +01:00
|
|
|
Assert.Equal(2, s.Driver.FindElements(By.CssSelector(".payment-method")).Count);
|
|
|
|
Assert.Contains("Bitcoin", s.Driver.FindElement(By.CssSelector(".payment-method.active")).Text);
|
|
|
|
Assert.Contains("LNURL", s.Driver.FindElement(By.CssSelector(".payment-method:nth-child(2)")).Text);
|
2023-02-10 03:23:48 +01:00
|
|
|
var qrValue = s.Driver.FindElement(By.CssSelector(".qr-container")).GetAttribute("data-qr-value");
|
|
|
|
var address = s.Driver.FindElement(By.CssSelector(".qr-container")).GetAttribute("data-clipboard");
|
2023-02-22 07:53:14 +01:00
|
|
|
var payUrl = s.Driver.FindElement(By.Id("PayInWallet")).GetAttribute("href");
|
2023-02-10 03:23:48 +01:00
|
|
|
var copyAddress = s.Driver.FindElement(By.Id("Address_BTC")).GetAttribute("value");
|
|
|
|
Assert.Equal($"bitcoin:{address}", payUrl);
|
|
|
|
Assert.StartsWith("bcrt", s.Driver.FindElement(By.Id("Address_BTC")).GetAttribute("value"));
|
2023-02-08 07:47:38 +01:00
|
|
|
Assert.DoesNotContain("lightning=", payUrl);
|
2023-02-10 03:23:48 +01:00
|
|
|
Assert.Equal(address, copyAddress);
|
|
|
|
Assert.Equal($"bitcoin:{address.ToUpperInvariant()}", qrValue);
|
|
|
|
s.Driver.ElementDoesNotExist(By.Id("Lightning_BTC"));
|
2023-01-24 10:10:38 +01:00
|
|
|
|
2023-03-13 02:12:58 +01:00
|
|
|
// Details should show exchange rate
|
|
|
|
s.Driver.ToggleCollapse("PaymentDetails");
|
|
|
|
s.Driver.ElementDoesNotExist(By.Id("PaymentDetails-TotalPrice"));
|
|
|
|
s.Driver.ElementDoesNotExist(By.Id("PaymentDetails-TotalFiat"));
|
|
|
|
s.Driver.ElementDoesNotExist(By.Id("PaymentDetails-AmountDue"));
|
|
|
|
Assert.Contains("$", s.Driver.FindElement(By.Id("PaymentDetails-ExchangeRate")).Text);
|
|
|
|
Assert.Contains("sat/byte", s.Driver.FindElement(By.Id("PaymentDetails-RecommendedFee")).Text);
|
|
|
|
|
2023-01-24 10:10:38 +01:00
|
|
|
// Switch to LNURL
|
|
|
|
s.Driver.FindElement(By.CssSelector(".payment-method:nth-child(2)")).Click();
|
|
|
|
TestUtils.Eventually(() =>
|
|
|
|
{
|
2023-02-22 07:53:14 +01:00
|
|
|
payUrl = s.Driver.FindElement(By.Id("PayInWallet")).GetAttribute("href");
|
2023-02-08 07:47:38 +01:00
|
|
|
Assert.StartsWith("lightning:lnurl", payUrl);
|
2023-02-10 03:23:48 +01:00
|
|
|
Assert.StartsWith("lnurl", s.Driver.WaitForElement(By.Id("Lightning_BTC")).GetAttribute("value"));
|
|
|
|
s.Driver.ElementDoesNotExist(By.Id("Address_BTC"));
|
2023-01-24 10:10:38 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
// Default payment method
|
|
|
|
s.GoToHome();
|
2023-03-13 02:12:58 +01:00
|
|
|
invoiceId = s.CreateInvoice(21000, "SATS", defaultPaymentMethod: "BTC_LightningLike");
|
2023-01-24 10:10:38 +01:00
|
|
|
s.GoToInvoiceCheckout(invoiceId);
|
2023-02-10 03:23:48 +01:00
|
|
|
s.Driver.WaitUntilAvailable(By.Id("Checkout-v2"));
|
2022-11-24 00:53:32 +01:00
|
|
|
Assert.Equal(2, s.Driver.FindElements(By.CssSelector(".payment-method")).Count);
|
2022-11-24 15:14:56 +01:00
|
|
|
Assert.Contains("Lightning", s.Driver.WaitForElement(By.CssSelector(".payment-method.active")).Text);
|
2023-02-08 07:47:38 +01:00
|
|
|
Assert.Contains("Bitcoin", s.Driver.WaitForElement(By.CssSelector(".payment-method")).Text);
|
2023-02-10 03:23:48 +01:00
|
|
|
qrValue = s.Driver.FindElement(By.CssSelector(".qr-container")).GetAttribute("data-qr-value");
|
|
|
|
address = s.Driver.FindElement(By.CssSelector(".qr-container")).GetAttribute("data-clipboard");
|
2023-02-22 07:53:14 +01:00
|
|
|
payUrl = s.Driver.FindElement(By.Id("PayInWallet")).GetAttribute("href");
|
2023-02-10 03:23:48 +01:00
|
|
|
copyAddress = s.Driver.FindElement(By.Id("Lightning_BTC_LightningLike")).GetAttribute("value");
|
|
|
|
Assert.Equal($"lightning:{address}", payUrl);
|
|
|
|
Assert.Equal(address, copyAddress);
|
|
|
|
Assert.Equal($"lightning:{address.ToUpperInvariant()}", qrValue);
|
|
|
|
s.Driver.ElementDoesNotExist(By.Id("Address_BTC"));
|
2023-01-06 14:18:07 +01:00
|
|
|
|
2023-03-09 21:36:11 +01:00
|
|
|
// Lightning amount in sats
|
2022-11-24 00:53:32 +01:00
|
|
|
Assert.Contains("BTC", s.Driver.FindElement(By.Id("AmountDue")).Text);
|
|
|
|
s.GoToHome();
|
|
|
|
s.GoToLightningSettings();
|
|
|
|
s.Driver.SetCheckbox(By.Id("LightningAmountInSatoshi"), true);
|
|
|
|
s.Driver.FindElement(By.Id("save")).Click();
|
|
|
|
Assert.Contains("BTC Lightning settings successfully updated", s.FindAlertMessage().Text);
|
|
|
|
s.GoToInvoiceCheckout(invoiceId);
|
2023-02-10 03:23:48 +01:00
|
|
|
s.Driver.WaitUntilAvailable(By.Id("Checkout-v2"));
|
2023-03-09 21:36:11 +01:00
|
|
|
Assert.Contains("sats", s.Driver.FindElement(By.Id("AmountDue")).Text);
|
2023-03-13 02:12:58 +01:00
|
|
|
|
|
|
|
// Details should not show exchange rate
|
|
|
|
s.Driver.ToggleCollapse("PaymentDetails");
|
|
|
|
s.Driver.ElementDoesNotExist(By.Id("PaymentDetails-ExchangeRate"));
|
|
|
|
s.Driver.ElementDoesNotExist(By.Id("PaymentDetails-TotalFiat"));
|
|
|
|
s.Driver.ElementDoesNotExist(By.Id("PaymentDetails-RecommendedFee"));
|
|
|
|
Assert.Contains("21 000 sats", s.Driver.FindElement(By.Id("PaymentDetails-AmountDue")).Text);
|
|
|
|
Assert.Contains("21 000 sats", s.Driver.FindElement(By.Id("PaymentDetails-TotalPrice")).Text);
|
2023-01-06 14:18:07 +01:00
|
|
|
|
2022-11-24 00:53:32 +01:00
|
|
|
// Expire
|
|
|
|
var expirySeconds = s.Driver.FindElement(By.Id("ExpirySeconds"));
|
|
|
|
expirySeconds.Clear();
|
|
|
|
expirySeconds.SendKeys("3");
|
|
|
|
s.Driver.FindElement(By.Id("Expire")).Click();
|
|
|
|
|
|
|
|
var paymentInfo = s.Driver.WaitForElement(By.Id("PaymentInfo"));
|
|
|
|
Assert.Contains("This invoice will expire in", paymentInfo.Text);
|
2022-11-24 15:14:56 +01:00
|
|
|
Assert.DoesNotContain("Please send", paymentInfo.Text);
|
2022-11-24 00:53:32 +01:00
|
|
|
TestUtils.Eventually(() =>
|
|
|
|
{
|
2023-03-27 12:12:11 +02:00
|
|
|
var expiredSection = s.Driver.FindElement(By.Id("unpaid"));
|
2022-11-24 00:53:32 +01:00
|
|
|
Assert.True(expiredSection.Displayed);
|
|
|
|
Assert.Contains("Invoice Expired", expiredSection.Text);
|
|
|
|
});
|
|
|
|
Assert.True(s.Driver.ElementDoesNotExist(By.Id("ReceiptLink")));
|
|
|
|
Assert.Equal(storeUrl, s.Driver.FindElement(By.Id("StoreLink")).GetAttribute("href"));
|
2023-01-06 14:18:07 +01:00
|
|
|
|
2022-11-24 00:53:32 +01:00
|
|
|
// Test payment
|
|
|
|
s.GoToHome();
|
|
|
|
invoiceId = s.CreateInvoice();
|
|
|
|
s.GoToInvoiceCheckout(invoiceId);
|
2023-02-10 03:23:48 +01:00
|
|
|
s.Driver.WaitUntilAvailable(By.Id("Checkout-v2"));
|
2023-01-06 14:18:07 +01:00
|
|
|
|
2022-11-24 00:53:32 +01:00
|
|
|
// Details
|
|
|
|
s.Driver.ToggleCollapse("PaymentDetails");
|
|
|
|
var details = s.Driver.FindElement(By.CssSelector(".payment-details"));
|
|
|
|
Assert.Contains("Total Price", details.Text);
|
|
|
|
Assert.Contains("Total Fiat", details.Text);
|
|
|
|
Assert.Contains("Exchange Rate", details.Text);
|
|
|
|
Assert.Contains("Amount Due", details.Text);
|
|
|
|
Assert.Contains("Recommended Fee", details.Text);
|
2023-03-13 02:12:58 +01:00
|
|
|
Assert.Contains("$", s.Driver.FindElement(By.Id("PaymentDetails-ExchangeRate")).Text);
|
|
|
|
Assert.Contains("$", s.Driver.FindElement(By.Id("PaymentDetails-TotalFiat")).Text);
|
|
|
|
Assert.Contains("BTC", s.Driver.FindElement(By.Id("PaymentDetails-AmountDue")).Text);
|
|
|
|
Assert.Contains("BTC", s.Driver.FindElement(By.Id("PaymentDetails-TotalPrice")).Text);
|
2023-01-06 14:18:07 +01:00
|
|
|
|
2022-11-24 00:53:32 +01:00
|
|
|
// Pay partial amount
|
|
|
|
await Task.Delay(200);
|
2023-02-10 03:23:48 +01:00
|
|
|
address = s.Driver.FindElement(By.CssSelector(".qr-container")).GetAttribute("data-clipboard");
|
2022-11-24 00:53:32 +01:00
|
|
|
var amountFraction = "0.00001";
|
|
|
|
await s.Server.ExplorerNode.SendToAddressAsync(BitcoinAddress.Create(address, Network.RegTest),
|
|
|
|
Money.Parse(amountFraction));
|
|
|
|
await s.Server.ExplorerNode.GenerateAsync(1);
|
2023-01-06 14:18:07 +01:00
|
|
|
|
2022-11-24 00:53:32 +01:00
|
|
|
// Fake Pay
|
|
|
|
s.Driver.FindElement(By.Id("FakePayAmount")).FillIn(amountFraction);
|
|
|
|
s.Driver.FindElement(By.Id("FakePay")).Click();
|
|
|
|
TestUtils.Eventually(() =>
|
|
|
|
{
|
|
|
|
Assert.Contains("Created transaction",
|
|
|
|
s.Driver.WaitForElement(By.Id("CheatSuccessMessage")).Text);
|
2023-03-27 12:12:11 +02:00
|
|
|
s.Server.ExplorerNode.Generate(2);
|
2022-11-24 15:14:56 +01:00
|
|
|
paymentInfo = s.Driver.WaitForElement(By.Id("PaymentInfo"));
|
|
|
|
Assert.Contains("The invoice hasn't been paid in full", paymentInfo.Text);
|
|
|
|
Assert.Contains("Please send", paymentInfo.Text);
|
2022-11-24 00:53:32 +01:00
|
|
|
});
|
|
|
|
|
2023-03-27 12:12:11 +02:00
|
|
|
// Pay full amount
|
|
|
|
var amountDue = s.Driver.FindElement(By.Id("AmountDue")).GetAttribute("data-amount-due");
|
|
|
|
s.Driver.FindElement(By.Id("FakePayAmount")).FillIn(amountDue);
|
|
|
|
s.Driver.FindElement(By.Id("FakePay")).Click();
|
|
|
|
|
|
|
|
// Processing
|
|
|
|
TestUtils.Eventually(() =>
|
|
|
|
{
|
|
|
|
var processingSection = s.Driver.WaitForElement(By.Id("processing"));
|
|
|
|
Assert.True(processingSection.Displayed);
|
2023-03-29 10:24:49 +02:00
|
|
|
Assert.Contains("Payment Received", processingSection.Text);
|
2023-03-27 12:12:11 +02:00
|
|
|
Assert.Contains("Your payment has been received and is now processing", processingSection.Text);
|
|
|
|
Assert.True(s.Driver.ElementDoesNotExist(By.Id("confetti")));
|
|
|
|
});
|
|
|
|
|
2022-11-24 00:53:32 +01:00
|
|
|
// Mine
|
|
|
|
s.Driver.FindElement(By.Id("Mine")).Click();
|
|
|
|
TestUtils.Eventually(() =>
|
|
|
|
{
|
|
|
|
Assert.Contains("Mined 1 block",
|
|
|
|
s.Driver.WaitForElement(By.Id("CheatSuccessMessage")).Text);
|
|
|
|
});
|
2023-03-27 12:12:11 +02:00
|
|
|
|
|
|
|
// Settled
|
2022-11-24 00:53:32 +01:00
|
|
|
TestUtils.Eventually(() =>
|
|
|
|
{
|
2023-03-27 12:12:11 +02:00
|
|
|
var settledSection = s.Driver.WaitForElement(By.Id("settled"));
|
|
|
|
Assert.True(settledSection.Displayed);
|
|
|
|
Assert.Contains("Invoice Paid", settledSection.Text);
|
2022-11-24 00:53:32 +01:00
|
|
|
});
|
2023-03-13 02:09:56 +01:00
|
|
|
s.Driver.FindElement(By.Id("confetti"));
|
2022-11-24 00:53:32 +01:00
|
|
|
s.Driver.FindElement(By.Id("ReceiptLink"));
|
|
|
|
Assert.Equal(storeUrl, s.Driver.FindElement(By.Id("StoreLink")).GetAttribute("href"));
|
2023-01-06 14:18:07 +01:00
|
|
|
|
2022-11-24 00:53:32 +01:00
|
|
|
// BIP21
|
|
|
|
s.GoToHome();
|
|
|
|
s.GoToStore(StoreNavPages.CheckoutAppearance);
|
|
|
|
s.Driver.SetCheckbox(By.Id("OnChainWithLnInvoiceFallback"), true);
|
2023-03-09 21:36:11 +01:00
|
|
|
s.Driver.SetCheckbox(By.Id("LightningAmountInSatoshi"), false);
|
2022-11-24 00:53:32 +01:00
|
|
|
s.Driver.FindElement(By.Id("Save")).Click();
|
|
|
|
Assert.Contains("Store successfully updated", s.FindAlertMessage().Text);
|
2023-01-06 14:18:07 +01:00
|
|
|
|
2022-11-24 00:53:32 +01:00
|
|
|
invoiceId = s.CreateInvoice();
|
|
|
|
s.GoToInvoiceCheckout(invoiceId);
|
2023-02-10 03:23:48 +01:00
|
|
|
s.Driver.WaitUntilAvailable(By.Id("Checkout-v2"));
|
2022-11-29 03:19:23 +01:00
|
|
|
Assert.Empty(s.Driver.FindElements(By.CssSelector(".payment-method")));
|
2023-03-09 21:36:11 +01:00
|
|
|
Assert.Contains("BTC", s.Driver.FindElement(By.Id("AmountDue")).Text);
|
2023-02-10 03:23:48 +01:00
|
|
|
qrValue = s.Driver.FindElement(By.CssSelector(".qr-container")).GetAttribute("data-qr-value");
|
|
|
|
address = s.Driver.FindElement(By.CssSelector(".qr-container")).GetAttribute("data-clipboard");
|
2023-02-22 07:53:14 +01:00
|
|
|
payUrl = s.Driver.FindElement(By.Id("PayInWallet")).GetAttribute("href");
|
2023-02-10 03:23:48 +01:00
|
|
|
var copyAddressOnchain = s.Driver.FindElement(By.Id("Address_BTC")).GetAttribute("value");
|
|
|
|
var copyAddressLightning = s.Driver.FindElement(By.Id("Lightning_BTC")).GetAttribute("value");
|
|
|
|
Assert.StartsWith($"bitcoin:{address}?amount=", payUrl);
|
|
|
|
Assert.Contains("?amount=", payUrl);
|
2023-01-24 01:44:39 +01:00
|
|
|
Assert.Contains("&lightning=", payUrl);
|
2023-02-10 03:23:48 +01:00
|
|
|
Assert.StartsWith("bcrt", copyAddressOnchain);
|
|
|
|
Assert.Equal(address, copyAddressOnchain);
|
|
|
|
Assert.StartsWith("lnbcrt", copyAddressLightning);
|
|
|
|
Assert.StartsWith($"bitcoin:{address.ToUpperInvariant()}?amount=", qrValue);
|
|
|
|
Assert.Contains("&lightning=LNBCRT", qrValue);
|
2023-03-09 21:36:11 +01:00
|
|
|
|
2023-03-13 02:12:58 +01:00
|
|
|
// Check details
|
|
|
|
s.Driver.ToggleCollapse("PaymentDetails");
|
|
|
|
Assert.Contains("1 BTC = ", s.Driver.FindElement(By.Id("PaymentDetails-ExchangeRate")).Text);
|
|
|
|
Assert.Contains("$", s.Driver.FindElement(By.Id("PaymentDetails-ExchangeRate")).Text);
|
|
|
|
Assert.Contains("$", s.Driver.FindElement(By.Id("PaymentDetails-TotalFiat")).Text);
|
|
|
|
Assert.Contains("BTC", s.Driver.FindElement(By.Id("PaymentDetails-AmountDue")).Text);
|
|
|
|
Assert.Contains("BTC", s.Driver.FindElement(By.Id("PaymentDetails-TotalPrice")).Text);
|
|
|
|
|
2023-03-09 21:36:11 +01:00
|
|
|
// Switch to amount displayed in sats
|
|
|
|
s.GoToHome();
|
|
|
|
s.GoToStore(StoreNavPages.CheckoutAppearance);
|
|
|
|
s.Driver.SetCheckbox(By.Id("LightningAmountInSatoshi"), true);
|
|
|
|
s.Driver.FindElement(By.Id("Save")).Click();
|
|
|
|
Assert.Contains("Store successfully updated", s.FindAlertMessage().Text);
|
|
|
|
s.GoToInvoiceCheckout(invoiceId);
|
|
|
|
s.Driver.WaitUntilAvailable(By.Id("Checkout-v2"));
|
|
|
|
Assert.Contains("sats", s.Driver.FindElement(By.Id("AmountDue")).Text);
|
2023-03-13 02:12:58 +01:00
|
|
|
|
|
|
|
// Check details
|
|
|
|
s.Driver.ToggleCollapse("PaymentDetails");
|
|
|
|
Assert.Contains("1 sat = ", s.Driver.FindElement(By.Id("PaymentDetails-ExchangeRate")).Text);
|
|
|
|
Assert.Contains("$", s.Driver.FindElement(By.Id("PaymentDetails-ExchangeRate")).Text);
|
|
|
|
Assert.Contains("$", s.Driver.FindElement(By.Id("PaymentDetails-TotalFiat")).Text);
|
|
|
|
Assert.Contains("sats", s.Driver.FindElement(By.Id("PaymentDetails-AmountDue")).Text);
|
|
|
|
Assert.Contains("sats", s.Driver.FindElement(By.Id("PaymentDetails-TotalPrice")).Text);
|
|
|
|
|
2022-11-29 03:19:23 +01:00
|
|
|
// BIP21 with LN as default payment method
|
|
|
|
s.GoToHome();
|
|
|
|
invoiceId = s.CreateInvoice(defaultPaymentMethod: "BTC_LightningLike");
|
|
|
|
s.GoToInvoiceCheckout(invoiceId);
|
2023-02-10 03:23:48 +01:00
|
|
|
s.Driver.WaitUntilAvailable(By.Id("Checkout-v2"));
|
2022-11-24 00:53:32 +01:00
|
|
|
Assert.Empty(s.Driver.FindElements(By.CssSelector(".payment-method")));
|
2023-02-22 07:53:14 +01:00
|
|
|
payUrl = s.Driver.FindElement(By.Id("PayInWallet")).GetAttribute("href");
|
2022-11-24 00:53:32 +01:00
|
|
|
Assert.StartsWith("bitcoin:", payUrl);
|
2023-02-08 07:47:38 +01:00
|
|
|
Assert.Contains("&lightning=lnbcrt", payUrl);
|
2023-03-13 02:12:58 +01:00
|
|
|
|
|
|
|
// Check details
|
|
|
|
s.Driver.ToggleCollapse("PaymentDetails");
|
|
|
|
Assert.Contains("1 sat = ", s.Driver.FindElement(By.Id("PaymentDetails-ExchangeRate")).Text);
|
|
|
|
Assert.Contains("$", s.Driver.FindElement(By.Id("PaymentDetails-ExchangeRate")).Text);
|
|
|
|
Assert.Contains("$", s.Driver.FindElement(By.Id("PaymentDetails-TotalFiat")).Text);
|
|
|
|
Assert.Contains("sats", s.Driver.FindElement(By.Id("PaymentDetails-AmountDue")).Text);
|
|
|
|
Assert.Contains("sats", s.Driver.FindElement(By.Id("PaymentDetails-TotalPrice")).Text);
|
2023-01-06 14:18:07 +01:00
|
|
|
|
2023-02-10 03:23:48 +01:00
|
|
|
// Ensure LNURL is enabled
|
2022-11-24 00:53:32 +01:00
|
|
|
s.GoToHome();
|
2023-02-10 03:23:48 +01:00
|
|
|
s.GoToLightningSettings();
|
|
|
|
Assert.True(s.Driver.FindElement(By.Id("LNURLEnabled")).Selected);
|
|
|
|
Assert.True(s.Driver.FindElement(By.Id("LNURLStandardInvoiceEnabled")).Selected);
|
|
|
|
|
2023-02-22 11:20:50 +01:00
|
|
|
// BIP21 with top-up invoice
|
2022-11-24 00:53:32 +01:00
|
|
|
invoiceId = s.CreateInvoice(amount: null);
|
|
|
|
s.GoToInvoiceCheckout(invoiceId);
|
2023-02-10 03:23:48 +01:00
|
|
|
s.Driver.WaitUntilAvailable(By.Id("Checkout-v2"));
|
2023-02-08 07:47:38 +01:00
|
|
|
Assert.Empty(s.Driver.FindElements(By.CssSelector(".payment-method")));
|
2023-02-10 03:23:48 +01:00
|
|
|
qrValue = s.Driver.FindElement(By.CssSelector(".qr-container")).GetAttribute("data-qr-value");
|
|
|
|
address = s.Driver.FindElement(By.CssSelector(".qr-container")).GetAttribute("data-clipboard");
|
2023-02-22 07:53:14 +01:00
|
|
|
payUrl = s.Driver.FindElement(By.Id("PayInWallet")).GetAttribute("href");
|
2023-02-10 03:23:48 +01:00
|
|
|
copyAddressOnchain = s.Driver.FindElement(By.Id("Address_BTC")).GetAttribute("value");
|
|
|
|
copyAddressLightning = s.Driver.FindElement(By.Id("Lightning_BTC")).GetAttribute("value");
|
|
|
|
Assert.StartsWith($"bitcoin:{address}", payUrl);
|
|
|
|
Assert.Contains("?lightning=lnurl", payUrl);
|
|
|
|
Assert.DoesNotContain("amount=", payUrl);
|
|
|
|
Assert.StartsWith("bcrt", copyAddressOnchain);
|
|
|
|
Assert.Equal(address, copyAddressOnchain);
|
|
|
|
Assert.StartsWith("lnurl", copyAddressLightning);
|
|
|
|
Assert.StartsWith($"bitcoin:{address.ToUpperInvariant()}?lightning=LNURL", qrValue);
|
2023-03-13 02:12:58 +01:00
|
|
|
|
|
|
|
// Check details
|
|
|
|
s.Driver.ToggleCollapse("PaymentDetails");
|
|
|
|
Assert.Contains("1 sat = ", s.Driver.FindElement(By.Id("PaymentDetails-ExchangeRate")).Text);
|
|
|
|
Assert.Contains("$", s.Driver.FindElement(By.Id("PaymentDetails-ExchangeRate")).Text);
|
|
|
|
s.Driver.ElementDoesNotExist(By.Id("PaymentDetails-TotalFiat"));
|
|
|
|
s.Driver.ElementDoesNotExist(By.Id("PaymentDetails-AmountDue"));
|
|
|
|
s.Driver.ElementDoesNotExist(By.Id("PaymentDetails-TotalPrice"));
|
2023-01-06 14:18:07 +01:00
|
|
|
|
2023-02-22 11:20:50 +01:00
|
|
|
// Expiry message should not show amount for top-up invoice
|
2022-11-24 15:14:56 +01:00
|
|
|
expirySeconds = s.Driver.FindElement(By.Id("ExpirySeconds"));
|
|
|
|
expirySeconds.Clear();
|
|
|
|
expirySeconds.SendKeys("5");
|
|
|
|
s.Driver.FindElement(By.Id("Expire")).Click();
|
|
|
|
|
|
|
|
paymentInfo = s.Driver.WaitForElement(By.Id("PaymentInfo"));
|
|
|
|
Assert.Contains("This invoice will expire in", paymentInfo.Text);
|
2023-01-16 12:45:19 +01:00
|
|
|
Assert.Contains("00:0", paymentInfo.Text);
|
2022-11-24 15:14:56 +01:00
|
|
|
Assert.DoesNotContain("Please send", paymentInfo.Text);
|
2023-01-16 12:45:19 +01:00
|
|
|
|
|
|
|
// Configure countdown timer
|
|
|
|
s.GoToHome();
|
|
|
|
invoiceId = s.CreateInvoice();
|
|
|
|
s.GoToHome();
|
|
|
|
s.GoToStore(StoreNavPages.CheckoutAppearance);
|
|
|
|
var displayExpirationTimer = s.Driver.FindElement(By.Id("DisplayExpirationTimer"));
|
|
|
|
Assert.Equal("5", displayExpirationTimer.GetAttribute("value"));
|
|
|
|
displayExpirationTimer.Clear();
|
|
|
|
displayExpirationTimer.SendKeys("10");
|
|
|
|
s.Driver.FindElement(By.Id("Save")).Click();
|
|
|
|
Assert.Contains("Store successfully updated", s.FindAlertMessage().Text);
|
|
|
|
|
|
|
|
s.GoToInvoiceCheckout(invoiceId);
|
2023-02-10 03:23:48 +01:00
|
|
|
s.Driver.WaitUntilAvailable(By.Id("Checkout-v2"));
|
2023-01-16 12:45:19 +01:00
|
|
|
paymentInfo = s.Driver.FindElement(By.Id("PaymentInfo"));
|
|
|
|
Assert.False(paymentInfo.Displayed);
|
|
|
|
Assert.DoesNotContain("This invoice will expire in", paymentInfo.Text);
|
|
|
|
|
|
|
|
expirySeconds = s.Driver.FindElement(By.Id("ExpirySeconds"));
|
|
|
|
expirySeconds.Clear();
|
|
|
|
expirySeconds.SendKeys("599");
|
|
|
|
s.Driver.FindElement(By.Id("Expire")).Click();
|
|
|
|
|
|
|
|
paymentInfo = s.Driver.WaitForElement(By.Id("PaymentInfo"));
|
|
|
|
Assert.True(paymentInfo.Displayed);
|
|
|
|
Assert.Contains("This invoice will expire in", paymentInfo.Text);
|
|
|
|
Assert.Contains("09:5", paymentInfo.Text);
|
2023-02-22 07:53:14 +01:00
|
|
|
|
|
|
|
// Disable LNURL again
|
|
|
|
s.GoToHome();
|
|
|
|
s.GoToLightningSettings();
|
|
|
|
s.Driver.SetCheckbox(By.Id("LNURLEnabled"), false);
|
|
|
|
s.Driver.FindElement(By.Id("save")).Click();
|
|
|
|
Assert.Contains("BTC Lightning settings successfully updated", s.FindAlertMessage().Text);
|
|
|
|
|
|
|
|
// Test:
|
|
|
|
// - NFC/LNURL-W available with just Lightning
|
|
|
|
// - BIP21 works correctly even though Lightning is default payment method
|
|
|
|
s.GoToHome();
|
|
|
|
invoiceId = s.CreateInvoice(defaultPaymentMethod: "BTC_LightningLike");
|
|
|
|
s.GoToInvoiceCheckout(invoiceId);
|
|
|
|
s.Driver.WaitUntilAvailable(By.Id("Checkout-v2"));
|
|
|
|
Assert.Empty(s.Driver.FindElements(By.CssSelector(".payment-method")));
|
|
|
|
payUrl = s.Driver.FindElement(By.Id("PayInWallet")).GetAttribute("href");
|
|
|
|
Assert.StartsWith("bitcoin:", payUrl);
|
|
|
|
Assert.Contains("&lightning=lnbcrt", payUrl);
|
2023-03-01 07:49:21 +01:00
|
|
|
|
|
|
|
// Language Switch
|
|
|
|
var languageSelect = new SelectElement(s.Driver.FindElement(By.Id("DefaultLang")));
|
|
|
|
Assert.Equal("English", languageSelect.SelectedOption.Text);
|
|
|
|
Assert.Equal("View Details", s.Driver.FindElement(By.Id("DetailsToggle")).Text);
|
|
|
|
Assert.DoesNotContain("lang=", s.Driver.Url);
|
|
|
|
languageSelect.SelectByText("Deutsch");
|
|
|
|
Assert.Equal("Details anzeigen", s.Driver.FindElement(By.Id("DetailsToggle")).Text);
|
|
|
|
Assert.Contains("lang=de", s.Driver.Url);
|
|
|
|
|
|
|
|
s.Driver.Navigate().Refresh();
|
|
|
|
languageSelect = new SelectElement(s.Driver.FindElement(By.Id("DefaultLang")));
|
|
|
|
Assert.Equal("Deutsch", languageSelect.SelectedOption.Text);
|
|
|
|
Assert.Equal("Details anzeigen", s.Driver.FindElement(By.Id("DetailsToggle")).Text);
|
|
|
|
languageSelect.SelectByText("English");
|
|
|
|
Assert.Equal("View Details", s.Driver.FindElement(By.Id("DetailsToggle")).Text);
|
|
|
|
Assert.Contains("lang=en", s.Driver.Url);
|
2022-11-24 00:53:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
[Fact(Timeout = TestTimeout)]
|
|
|
|
public async Task CanUseCheckoutAsModal()
|
|
|
|
{
|
|
|
|
using var s = CreateSeleniumTester();
|
|
|
|
await s.StartAsync();
|
|
|
|
s.GoToRegister();
|
|
|
|
s.RegisterNewUser();
|
|
|
|
s.CreateNewStore();
|
|
|
|
s.EnableCheckoutV2();
|
|
|
|
s.GoToStore();
|
|
|
|
s.AddDerivationScheme();
|
|
|
|
var invoiceId = s.CreateInvoice(0.001m, "BTC", "a@x.com");
|
|
|
|
var invoice = await s.Server.PayTester.InvoiceRepository.GetInvoice(invoiceId);
|
|
|
|
s.Driver.Navigate()
|
|
|
|
.GoToUrl(new Uri(s.ServerUri, $"tests/index.html?invoice={invoiceId}"));
|
2022-12-10 11:19:13 +01:00
|
|
|
s.Driver.WaitUntilAvailable(By.Name("btcpay"));
|
2023-01-06 14:18:07 +01:00
|
|
|
|
2022-12-10 11:19:13 +01:00
|
|
|
var frameElement = s.Driver.FindElement(By.Name("btcpay"));
|
|
|
|
Assert.True(frameElement.Displayed);
|
|
|
|
var iframe = s.Driver.SwitchTo().Frame(frameElement);
|
|
|
|
iframe.WaitUntilAvailable(By.Id("Checkout-v2"));
|
2023-01-06 14:18:07 +01:00
|
|
|
|
2022-11-24 00:53:32 +01:00
|
|
|
await s.Server.ExplorerNode.SendToAddressAsync(BitcoinAddress.Create(invoice
|
|
|
|
.GetPaymentMethod(new PaymentMethodId("BTC", PaymentTypes.BTCLike))
|
|
|
|
.GetPaymentMethodDetails().GetPaymentDestination(), Network.RegTest),
|
|
|
|
new Money(0.001m, MoneyUnit.BTC));
|
|
|
|
|
|
|
|
IWebElement closebutton = null;
|
|
|
|
TestUtils.Eventually(() =>
|
|
|
|
{
|
|
|
|
closebutton = iframe.FindElement(By.Id("close"));
|
|
|
|
Assert.True(closebutton.Displayed);
|
|
|
|
});
|
|
|
|
closebutton.Click();
|
|
|
|
s.Driver.AssertElementNotFound(By.Name("btcpay"));
|
|
|
|
Assert.Equal(s.Driver.Url,
|
|
|
|
new Uri(s.ServerUri, $"tests/index.html?invoice={invoiceId}").ToString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|