mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2024-11-19 09:54:30 +01:00
Revert "Share same browser for all selenium tests"
This reverts commit 2ce0749bb6
.
This commit is contained in:
parent
60a8b23c03
commit
41d714e2ce
@ -19,16 +19,12 @@ using OpenQA.Selenium;
|
||||
|
||||
namespace BTCPayServer.Tests
|
||||
{
|
||||
[Collection("Selenium collection")]
|
||||
public class AuthenticationTests
|
||||
{
|
||||
public SeleniumTester SeleniumTester { get; }
|
||||
|
||||
public AuthenticationTests(ITestOutputHelper helper, SeleniumTester seleniumTester)
|
||||
public AuthenticationTests(ITestOutputHelper helper)
|
||||
{
|
||||
Logs.Tester = new XUnitLog(helper) { Name = "Tests" };
|
||||
Logs.Tester = new XUnitLog(helper) {Name = "Tests"};
|
||||
Logs.LogProvider = new XUnitLogProvider(helper);
|
||||
SeleniumTester = seleniumTester;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -97,45 +93,49 @@ namespace BTCPayServer.Tests
|
||||
[Fact]
|
||||
public async Task CanUseImplicitFlow()
|
||||
{
|
||||
var tester = SeleniumTester.Server;
|
||||
using (var s = SeleniumTester.Create())
|
||||
{
|
||||
s.Start();
|
||||
var tester = s.Server;
|
||||
|
||||
var user = tester.NewAccount();
|
||||
user.GrantAccess();
|
||||
var id = Guid.NewGuid().ToString();
|
||||
var redirecturi = new Uri("http://127.0.0.1/oidc-callback");
|
||||
var openIdClient = await user.RegisterOpenIdClient(
|
||||
new OpenIddictApplicationDescriptor()
|
||||
{
|
||||
ClientId = id,
|
||||
DisplayName = id,
|
||||
Permissions = { OpenIddictConstants.Permissions.GrantTypes.Implicit },
|
||||
RedirectUris = { redirecturi }
|
||||
});
|
||||
var implicitAuthorizeUrl = new Uri(tester.PayTester.ServerUri,
|
||||
$"connect/authorize?response_type=token&client_id={id}&redirect_uri={redirecturi.AbsoluteUri}&scope=openid&nonce={Guid.NewGuid().ToString()}");
|
||||
SeleniumTester.Driver.Navigate().GoToUrl(implicitAuthorizeUrl);
|
||||
SeleniumTester.Login(user.RegisterDetails.Email, user.RegisterDetails.Password);
|
||||
SeleniumTester.Driver.FindElement(By.Id("consent-yes")).Click();
|
||||
var url = SeleniumTester.Driver.Url;
|
||||
var results = url.Split("#").Last().Split("&")
|
||||
.ToDictionary(s1 => s1.Split("=")[0], s1 => s1.Split("=")[1]);
|
||||
await TestApiAgainstAccessToken(results["access_token"], tester, user);
|
||||
//in Implicit mode, you renew your token by hitting the same endpoint but adding prompt=none. If you are still logged in on the site, you will receive a fresh token.
|
||||
var implicitAuthorizeUrlSilentModel = new Uri($"{implicitAuthorizeUrl.OriginalString}&prompt=none");
|
||||
SeleniumTester.Driver.Navigate().GoToUrl(implicitAuthorizeUrlSilentModel);
|
||||
url = SeleniumTester.Driver.Url;
|
||||
results = url.Split("#").Last().Split("&").ToDictionary(s1 => s1.Split("=")[0], s1 => s1.Split("=")[1]);
|
||||
await TestApiAgainstAccessToken(results["access_token"], tester, user);
|
||||
var user = tester.NewAccount();
|
||||
user.GrantAccess();
|
||||
var id = Guid.NewGuid().ToString();
|
||||
var redirecturi = new Uri("http://127.0.0.1/oidc-callback");
|
||||
var openIdClient = await user.RegisterOpenIdClient(
|
||||
new OpenIddictApplicationDescriptor()
|
||||
{
|
||||
ClientId = id,
|
||||
DisplayName = id,
|
||||
Permissions = {OpenIddictConstants.Permissions.GrantTypes.Implicit},
|
||||
RedirectUris = {redirecturi}
|
||||
});
|
||||
var implicitAuthorizeUrl = new Uri(tester.PayTester.ServerUri,
|
||||
$"connect/authorize?response_type=token&client_id={id}&redirect_uri={redirecturi.AbsoluteUri}&scope=openid&nonce={Guid.NewGuid().ToString()}");
|
||||
s.Driver.Navigate().GoToUrl(implicitAuthorizeUrl);
|
||||
s.Login(user.RegisterDetails.Email, user.RegisterDetails.Password);
|
||||
s.Driver.FindElement(By.Id("consent-yes")).Click();
|
||||
var url = s.Driver.Url;
|
||||
var results = url.Split("#").Last().Split("&")
|
||||
.ToDictionary(s1 => s1.Split("=")[0], s1 => s1.Split("=")[1]);
|
||||
await TestApiAgainstAccessToken(results["access_token"], tester, user);
|
||||
//in Implicit mode, you renew your token by hitting the same endpoint but adding prompt=none. If you are still logged in on the site, you will receive a fresh token.
|
||||
var implicitAuthorizeUrlSilentModel = new Uri($"{implicitAuthorizeUrl.OriginalString}&prompt=none");
|
||||
s.Driver.Navigate().GoToUrl(implicitAuthorizeUrlSilentModel);
|
||||
url = s.Driver.Url;
|
||||
results = url.Split("#").Last().Split("&").ToDictionary(s1 => s1.Split("=")[0], s1 => s1.Split("=")[1]);
|
||||
await TestApiAgainstAccessToken(results["access_token"], tester, user);
|
||||
|
||||
LogoutFlow(tester, id, SeleniumTester);
|
||||
|
||||
SeleniumTester.Driver.Navigate().GoToUrl(implicitAuthorizeUrl);
|
||||
SeleniumTester.Login(user.RegisterDetails.Email, user.RegisterDetails.Password);
|
||||
|
||||
Assert.Throws<NoSuchElementException>(() => SeleniumTester.Driver.FindElement(By.Id("consent-yes")));
|
||||
results = url.Split("#").Last().Split("&")
|
||||
.ToDictionary(s1 => s1.Split("=")[0], s1 => s1.Split("=")[1]);
|
||||
await TestApiAgainstAccessToken(results["access_token"], tester, user);
|
||||
LogoutFlow(tester, id, s);
|
||||
|
||||
s.Driver.Navigate().GoToUrl(implicitAuthorizeUrl);
|
||||
s.Login(user.RegisterDetails.Email, user.RegisterDetails.Password);
|
||||
|
||||
Assert.Throws<NoSuchElementException>(() => s.Driver.FindElement(By.Id("consent-yes")));
|
||||
results = url.Split("#").Last().Split("&")
|
||||
.ToDictionary(s1 => s1.Split("=")[0], s1 => s1.Split("=")[1]);
|
||||
await TestApiAgainstAccessToken(results["access_token"], tester, user);
|
||||
}
|
||||
}
|
||||
|
||||
void LogoutFlow(ServerTester tester, string clientId, SeleniumTester seleniumTester)
|
||||
@ -145,47 +145,50 @@ namespace BTCPayServer.Tests
|
||||
seleniumTester.Driver.Navigate().GoToUrl(logoutUrl);
|
||||
seleniumTester.GoToHome();
|
||||
Assert.Throws<NoSuchElementException>(() => seleniumTester.Driver.FindElement(By.Id("Logout")));
|
||||
|
||||
|
||||
}
|
||||
|
||||
[Trait("Selenium", "Selenium")]
|
||||
[Fact]
|
||||
public async Task CanUseCodeFlow()
|
||||
{
|
||||
var tester = SeleniumTester.Server;
|
||||
using (var s = SeleniumTester.Create())
|
||||
{
|
||||
s.Start();
|
||||
var tester = s.Server;
|
||||
|
||||
var user = tester.NewAccount();
|
||||
user.GrantAccess();
|
||||
var id = Guid.NewGuid().ToString();
|
||||
var redirecturi = new Uri("http://127.0.0.1/oidc-callback");
|
||||
var secret = "secret";
|
||||
var openIdClient = await user.RegisterOpenIdClient(
|
||||
new OpenIddictApplicationDescriptor()
|
||||
{
|
||||
ClientId = id,
|
||||
DisplayName = id,
|
||||
Permissions =
|
||||
var user = tester.NewAccount();
|
||||
user.GrantAccess();
|
||||
var id = Guid.NewGuid().ToString();
|
||||
var redirecturi = new Uri("http://127.0.0.1/oidc-callback");
|
||||
var secret = "secret";
|
||||
var openIdClient = await user.RegisterOpenIdClient(
|
||||
new OpenIddictApplicationDescriptor()
|
||||
{
|
||||
ClientId = id,
|
||||
DisplayName = id,
|
||||
Permissions =
|
||||
{
|
||||
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode,
|
||||
OpenIddictConstants.Permissions.GrantTypes.RefreshToken
|
||||
},
|
||||
RedirectUris = { redirecturi }
|
||||
}, secret);
|
||||
var authorizeUrl = new Uri(tester.PayTester.ServerUri,
|
||||
$"connect/authorize?response_type=code&client_id={id}&redirect_uri={redirecturi.AbsoluteUri}&scope=openid offline_access&state={Guid.NewGuid().ToString()}");
|
||||
SeleniumTester.Driver.Navigate().GoToUrl(authorizeUrl);
|
||||
SeleniumTester.Login(user.RegisterDetails.Email, user.RegisterDetails.Password);
|
||||
SeleniumTester.Driver.FindElement(By.Id("consent-yes")).Click();
|
||||
var url = SeleniumTester.Driver.Url;
|
||||
var results = url.Split("?").Last().Split("&")
|
||||
.ToDictionary(s1 => s1.Split("=")[0], s1 => s1.Split("=")[1]);
|
||||
},
|
||||
RedirectUris = {redirecturi}
|
||||
}, secret);
|
||||
var authorizeUrl = new Uri(tester.PayTester.ServerUri,
|
||||
$"connect/authorize?response_type=code&client_id={id}&redirect_uri={redirecturi.AbsoluteUri}&scope=openid offline_access&state={Guid.NewGuid().ToString()}");
|
||||
s.Driver.Navigate().GoToUrl(authorizeUrl);
|
||||
s.Login(user.RegisterDetails.Email, user.RegisterDetails.Password);
|
||||
s.Driver.FindElement(By.Id("consent-yes")).Click();
|
||||
var url = s.Driver.Url;
|
||||
var results = url.Split("?").Last().Split("&")
|
||||
.ToDictionary(s1 => s1.Split("=")[0], s1 => s1.Split("=")[1]);
|
||||
|
||||
var httpClient = tester.PayTester.HttpClient;
|
||||
var httpClient = tester.PayTester.HttpClient;
|
||||
|
||||
var httpRequest = new HttpRequestMessage(HttpMethod.Post,
|
||||
new Uri(tester.PayTester.ServerUri, "/connect/token"))
|
||||
{
|
||||
Content = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>()
|
||||
var httpRequest = new HttpRequestMessage(HttpMethod.Post,
|
||||
new Uri(tester.PayTester.ServerUri, "/connect/token"))
|
||||
{
|
||||
Content = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>()
|
||||
{
|
||||
new KeyValuePair<string, string>("grant_type",
|
||||
OpenIddictConstants.GrantTypes.AuthorizationCode),
|
||||
@ -194,30 +197,31 @@ namespace BTCPayServer.Tests
|
||||
new KeyValuePair<string, string>("code", results["code"]),
|
||||
new KeyValuePair<string, string>("redirect_uri", redirecturi.AbsoluteUri)
|
||||
})
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
var response = await httpClient.SendAsync(httpRequest);
|
||||
var response = await httpClient.SendAsync(httpRequest);
|
||||
|
||||
Assert.True(response.IsSuccessStatusCode);
|
||||
Assert.True(response.IsSuccessStatusCode);
|
||||
|
||||
string content = await response.Content.ReadAsStringAsync();
|
||||
var result = JObject.Parse(content).ToObject<OpenIdConnectResponse>();
|
||||
string content = await response.Content.ReadAsStringAsync();
|
||||
var result = JObject.Parse(content).ToObject<OpenIdConnectResponse>();
|
||||
|
||||
await TestApiAgainstAccessToken(result.AccessToken, tester, user);
|
||||
await TestApiAgainstAccessToken(result.AccessToken, tester, user);
|
||||
|
||||
var refreshedAccessToken = await RefreshAnAccessToken(result.RefreshToken, httpClient, id, secret);
|
||||
var refreshedAccessToken = await RefreshAnAccessToken(result.RefreshToken, httpClient, id, secret);
|
||||
|
||||
await TestApiAgainstAccessToken(refreshedAccessToken, tester, user);
|
||||
|
||||
LogoutFlow(tester, id, SeleniumTester);
|
||||
SeleniumTester.Driver.Navigate().GoToUrl(authorizeUrl);
|
||||
SeleniumTester.Login(user.RegisterDetails.Email, user.RegisterDetails.Password);
|
||||
|
||||
Assert.Throws<NoSuchElementException>(() => SeleniumTester.Driver.FindElement(By.Id("consent-yes")));
|
||||
results = url.Split("?").Last().Split("&")
|
||||
.ToDictionary(s1 => s1.Split("=")[0], s1 => s1.Split("=")[1]);
|
||||
Assert.True(results.ContainsKey("code"));
|
||||
await TestApiAgainstAccessToken(refreshedAccessToken, tester, user);
|
||||
|
||||
LogoutFlow(tester, id, s);
|
||||
s.Driver.Navigate().GoToUrl(authorizeUrl);
|
||||
s.Login(user.RegisterDetails.Email, user.RegisterDetails.Password);
|
||||
|
||||
Assert.Throws<NoSuchElementException>(() => s.Driver.FindElement(By.Id("consent-yes")));
|
||||
results = url.Split("?").Last().Split("&")
|
||||
.ToDictionary(s1 => s1.Split("=")[0], s1 => s1.Split("=")[1]);
|
||||
Assert.True(results.ContainsKey("code"));
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<string> RefreshAnAccessToken(string refreshToken, HttpClient client, string clientId,
|
||||
@ -257,7 +261,7 @@ namespace BTCPayServer.Tests
|
||||
{
|
||||
ClientId = id,
|
||||
DisplayName = id,
|
||||
Permissions = { OpenIddictConstants.Permissions.GrantTypes.ClientCredentials }
|
||||
Permissions = {OpenIddictConstants.Permissions.GrantTypes.ClientCredentials}
|
||||
}, secret);
|
||||
|
||||
|
||||
@ -296,7 +300,7 @@ namespace BTCPayServer.Tests
|
||||
{
|
||||
ClientId = id,
|
||||
DisplayName = id,
|
||||
Permissions = { OpenIddictConstants.Permissions.GrantTypes.Password }
|
||||
Permissions = {OpenIddictConstants.Permissions.GrantTypes.Password}
|
||||
}, secret);
|
||||
|
||||
|
||||
|
@ -15,140 +15,163 @@ using Xunit.Abstractions;
|
||||
namespace BTCPayServer.Tests
|
||||
{
|
||||
[Trait("Selenium", "Selenium")]
|
||||
[Collection("Selenium collection")]
|
||||
public class CheckoutUITests
|
||||
{
|
||||
public SeleniumTester SeleniumTester { get; }
|
||||
|
||||
public CheckoutUITests(ITestOutputHelper helper, SeleniumTester seleniumTester)
|
||||
public CheckoutUITests(ITestOutputHelper helper)
|
||||
{
|
||||
Logs.Tester = new XUnitLog(helper) { Name = "Tests" };
|
||||
Logs.Tester = new XUnitLog(helper) {Name = "Tests"};
|
||||
Logs.LogProvider = new XUnitLogProvider(helper);
|
||||
SeleniumTester = seleniumTester;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
[Fact]
|
||||
public void CanCreateInvoice()
|
||||
{
|
||||
SeleniumTester.RegisterNewUser();
|
||||
var store = SeleniumTester.CreateNewStore().storeName;
|
||||
SeleniumTester.AddDerivationScheme();
|
||||
using (var s = SeleniumTester.Create())
|
||||
{
|
||||
s.Start();
|
||||
s.RegisterNewUser();
|
||||
var store = s.CreateNewStore().storeName;
|
||||
s.AddDerivationScheme();
|
||||
|
||||
SeleniumTester.CreateInvoice(store);
|
||||
s.CreateInvoice(store);
|
||||
|
||||
SeleniumTester.Driver.FindElement(By.ClassName("invoice-details-link")).Click();
|
||||
SeleniumTester.Driver.AssertNoError();
|
||||
SeleniumTester.Driver.Navigate().Back();
|
||||
SeleniumTester.Driver.FindElement(By.ClassName("invoice-checkout-link")).Click();
|
||||
Assert.NotEmpty(SeleniumTester.Driver.FindElements(By.Id("checkoutCtrl")));
|
||||
s.Driver.FindElement(By.ClassName("invoice-details-link")).Click();
|
||||
s.Driver.AssertNoError();
|
||||
s.Driver.Navigate().Back();
|
||||
s.Driver.FindElement(By.ClassName("invoice-checkout-link")).Click();
|
||||
Assert.NotEmpty(s.Driver.FindElements(By.Id("checkoutCtrl")));
|
||||
s.Driver.Quit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public async Task CanHandleRefundEmailForm()
|
||||
{
|
||||
SeleniumTester.RegisterNewUser();
|
||||
var store = SeleniumTester.CreateNewStore();
|
||||
SeleniumTester.AddDerivationScheme("BTC");
|
||||
|
||||
var emailAlreadyThereInvoiceId = SeleniumTester.CreateInvoice(store.storeName, 100, "USD", "a@g.com");
|
||||
SeleniumTester.GoToInvoiceCheckout(emailAlreadyThereInvoiceId);
|
||||
SeleniumTester.Driver.AssertElementNotFound(By.Id("emailAddressFormInput"));
|
||||
SeleniumTester.GoToHome();
|
||||
var invoiceId = SeleniumTester.CreateInvoice(store.storeName);
|
||||
SeleniumTester.GoToInvoiceCheckout(invoiceId);
|
||||
Assert.True(SeleniumTester.Driver.FindElement(By.Id("emailAddressFormInput")).Displayed);
|
||||
SeleniumTester.Driver.FindElement(By.Id("emailAddressFormInput")).SendKeys("xxx");
|
||||
SeleniumTester.Driver.FindElement(By.Id("emailAddressForm")).FindElement(By.CssSelector("button.action-button"))
|
||||
.Click();
|
||||
using (var s = SeleniumTester.Create())
|
||||
{
|
||||
s.Start();
|
||||
s.RegisterNewUser();
|
||||
var store = s.CreateNewStore();
|
||||
s.AddDerivationScheme("BTC");
|
||||
|
||||
Assert.True(SeleniumTester.Driver.FindElement(By.Id("emailAddressFormInput")).Displayed);
|
||||
SeleniumTester.Driver.FindElement(By.Id("emailAddressFormInput")).SendKeys("@g.com");
|
||||
SeleniumTester.Driver.FindElement(By.Id("emailAddressForm")).FindElement(By.CssSelector("button.action-button"))
|
||||
.Click();
|
||||
var emailAlreadyThereInvoiceId =s.CreateInvoice(store.storeName, 100, "USD", "a@g.com");
|
||||
s.GoToInvoiceCheckout(emailAlreadyThereInvoiceId);
|
||||
s.Driver.AssertElementNotFound(By.Id("emailAddressFormInput"));
|
||||
s.GoToHome();
|
||||
var invoiceId = s.CreateInvoice(store.storeName);
|
||||
s.GoToInvoiceCheckout(invoiceId);
|
||||
Assert.True(s.Driver.FindElement(By.Id("emailAddressFormInput")).Displayed);
|
||||
s.Driver.FindElement(By.Id("emailAddressFormInput")).SendKeys("xxx");
|
||||
s.Driver.FindElement(By.Id("emailAddressForm")).FindElement(By.CssSelector("button.action-button"))
|
||||
.Click();
|
||||
|
||||
Assert.True(s.Driver.FindElement(By.Id("emailAddressFormInput")).Displayed);
|
||||
s.Driver.FindElement(By.Id("emailAddressFormInput")).SendKeys("@g.com");
|
||||
s.Driver.FindElement(By.Id("emailAddressForm")).FindElement(By.CssSelector("button.action-button"))
|
||||
.Click();
|
||||
|
||||
await Task.Delay(1000);
|
||||
SeleniumTester.Driver.AssertElementNotFound(By.Id("emailAddressFormInput"));
|
||||
await Task.Delay(1000);
|
||||
s.Driver.AssertElementNotFound(By.Id("emailAddressFormInput"));
|
||||
|
||||
s.Driver.Navigate().Refresh();
|
||||
|
||||
SeleniumTester.Driver.Navigate().Refresh();
|
||||
|
||||
SeleniumTester.Driver.AssertElementNotFound(By.Id("emailAddressFormInput"));
|
||||
s.Driver.AssertElementNotFound(By.Id("emailAddressFormInput"));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanUseLanguageDropdown()
|
||||
{
|
||||
SeleniumTester.RegisterNewUser();
|
||||
var store = SeleniumTester.CreateNewStore();
|
||||
SeleniumTester.AddDerivationScheme("BTC");
|
||||
using (var s = SeleniumTester.Create())
|
||||
{
|
||||
s.Start();
|
||||
s.RegisterNewUser();
|
||||
var store = s.CreateNewStore();
|
||||
s.AddDerivationScheme("BTC");
|
||||
|
||||
var invoiceId = SeleniumTester.CreateInvoice(store.storeName);
|
||||
SeleniumTester.GoToInvoiceCheckout(invoiceId);
|
||||
Assert.True(SeleniumTester.Driver.FindElement(By.Id("DefaultLang")).FindElements(By.TagName("option")).Count > 1);
|
||||
var payWithTextEnglish = SeleniumTester.Driver.FindElement(By.Id("pay-with-text")).Text;
|
||||
|
||||
var prettyDropdown = SeleniumTester.Driver.FindElement(By.Id("prettydropdown-DefaultLang"));
|
||||
prettyDropdown.Click();
|
||||
await Task.Delay(200);
|
||||
prettyDropdown.FindElement(By.CssSelector("[data-value=\"da-DK\"]")).Click();
|
||||
await Task.Delay(1000);
|
||||
Assert.NotEqual(payWithTextEnglish, SeleniumTester.Driver.FindElement(By.Id("pay-with-text")).Text);
|
||||
SeleniumTester.Driver.Navigate().GoToUrl(SeleniumTester.Driver.Url + "?lang=da-DK");
|
||||
|
||||
Assert.NotEqual(payWithTextEnglish, SeleniumTester.Driver.FindElement(By.Id("pay-with-text")).Text);
|
||||
var invoiceId = s.CreateInvoice(store.storeName);
|
||||
s.GoToInvoiceCheckout(invoiceId);
|
||||
Assert.True(s.Driver.FindElement(By.Id("DefaultLang")).FindElements(By.TagName("option")).Count > 1);
|
||||
var payWithTextEnglish = s.Driver.FindElement(By.Id("pay-with-text")).Text;
|
||||
|
||||
var prettyDropdown = s.Driver.FindElement(By.Id("prettydropdown-DefaultLang"));
|
||||
prettyDropdown.Click();
|
||||
await Task.Delay(200);
|
||||
prettyDropdown.FindElement(By.CssSelector("[data-value=\"da-DK\"]")).Click();
|
||||
await Task.Delay(1000);
|
||||
Assert.NotEqual(payWithTextEnglish, s.Driver.FindElement(By.Id("pay-with-text")).Text);
|
||||
s.Driver.Navigate().GoToUrl(s.Driver.Url + "?lang=da-DK");
|
||||
|
||||
Assert.NotEqual(payWithTextEnglish, s.Driver.FindElement(By.Id("pay-with-text")).Text);
|
||||
|
||||
s.Driver.Quit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void CanUsePaymentMethodDropdown()
|
||||
{
|
||||
SeleniumTester.RegisterNewUser();
|
||||
var store = SeleniumTester.CreateNewStore();
|
||||
SeleniumTester.AddDerivationScheme("BTC");
|
||||
|
||||
//check that there is no dropdown since only one payment method is set
|
||||
var invoiceId = SeleniumTester.CreateInvoice(store.storeName, 10, "USD", "a@g.com");
|
||||
SeleniumTester.GoToInvoiceCheckout(invoiceId);
|
||||
SeleniumTester.Driver.FindElement(By.ClassName("payment__currencies_noborder"));
|
||||
SeleniumTester.GoToHome();
|
||||
SeleniumTester.GoToStore(store.storeId);
|
||||
SeleniumTester.AddDerivationScheme("LTC");
|
||||
SeleniumTester.AddLightningNode("BTC", LightningConnectionType.CLightning);
|
||||
//there should be three now
|
||||
invoiceId = SeleniumTester.CreateInvoice(store.storeName, 10, "USD", "a@g.com");
|
||||
SeleniumTester.GoToInvoiceCheckout(invoiceId);
|
||||
var currencyDropdownButton = SeleniumTester.Driver.FindElement(By.ClassName("payment__currencies"));
|
||||
Assert.Contains("BTC", currencyDropdownButton.Text);
|
||||
currencyDropdownButton.Click();
|
||||
|
||||
var elements = SeleniumTester.Driver.FindElement(By.ClassName("vex-content"))
|
||||
.FindElements(By.ClassName("vexmenuitem"));
|
||||
Assert.Equal(3, elements.Count);
|
||||
elements.Single(element => element.Text.Contains("LTC")).Click();
|
||||
currencyDropdownButton = SeleniumTester.Driver.FindElement(By.ClassName("payment__currencies"));
|
||||
Assert.Contains("LTC", currencyDropdownButton.Text);
|
||||
|
||||
elements = SeleniumTester.Driver.FindElement(By.ClassName("vex-content"))
|
||||
.FindElements(By.ClassName("vexmenuitem"));
|
||||
|
||||
elements.Single(element => element.Text.Contains("Lightning")).Click();
|
||||
|
||||
Assert.Contains("Lightning", currencyDropdownButton.Text);
|
||||
using (var s = SeleniumTester.Create())
|
||||
{
|
||||
s.Start();
|
||||
s.RegisterNewUser();
|
||||
var store = s.CreateNewStore();
|
||||
s.AddDerivationScheme("BTC");
|
||||
|
||||
//check that there is no dropdown since only one payment method is set
|
||||
var invoiceId = s.CreateInvoice(store.storeName, 10, "USD", "a@g.com");
|
||||
s.GoToInvoiceCheckout(invoiceId);
|
||||
s.Driver.FindElement(By.ClassName("payment__currencies_noborder"));
|
||||
s.GoToHome();
|
||||
s.GoToStore(store.storeId);
|
||||
s.AddDerivationScheme("LTC");
|
||||
s.AddLightningNode("BTC",LightningConnectionType.CLightning);
|
||||
//there should be three now
|
||||
invoiceId = s.CreateInvoice(store.storeName, 10, "USD", "a@g.com");
|
||||
s.GoToInvoiceCheckout(invoiceId);
|
||||
var currencyDropdownButton = s.Driver.FindElement(By.ClassName("payment__currencies"));
|
||||
Assert.Contains("BTC", currencyDropdownButton.Text);
|
||||
currencyDropdownButton.Click();
|
||||
|
||||
var elements = s.Driver.FindElement(By.ClassName("vex-content"))
|
||||
.FindElements(By.ClassName("vexmenuitem"));
|
||||
Assert.Equal(3, elements.Count);
|
||||
elements.Single(element => element.Text.Contains("LTC")).Click();
|
||||
currencyDropdownButton = s.Driver.FindElement(By.ClassName("payment__currencies"));
|
||||
Assert.Contains("LTC", currencyDropdownButton.Text);
|
||||
|
||||
elements = s.Driver.FindElement(By.ClassName("vex-content"))
|
||||
.FindElements(By.ClassName("vexmenuitem"));
|
||||
|
||||
elements.Single(element => element.Text.Contains("Lightning")).Click();
|
||||
|
||||
Assert.Contains("Lightning", currencyDropdownButton.Text);
|
||||
|
||||
s.Driver.Quit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void CanUseLightningSatsFeature()
|
||||
{
|
||||
SeleniumTester.RegisterNewUser();
|
||||
var store = SeleniumTester.CreateNewStore();
|
||||
SeleniumTester.AddInternalLightningNode("BTC");
|
||||
SeleniumTester.GoToStore(store.storeId, StoreNavPages.Checkout);
|
||||
SeleniumTester.SetCheckbox(SeleniumTester, "LightningAmountInSatoshi", true);
|
||||
var command = SeleniumTester.Driver.FindElement(By.Name("command"));
|
||||
|
||||
command.ForceClick();
|
||||
var invoiceId = SeleniumTester.CreateInvoice(store.storeName, 10, "USD", "a@g.com");
|
||||
SeleniumTester.GoToInvoiceCheckout(invoiceId);
|
||||
Assert.Contains("Sats", SeleniumTester.Driver.FindElement(By.ClassName("payment__currencies_noborder")).Text);
|
||||
using (var s = SeleniumTester.Create())
|
||||
{
|
||||
s.Start();
|
||||
s.RegisterNewUser();
|
||||
var store = s.CreateNewStore();
|
||||
s.AddInternalLightningNode("BTC");
|
||||
s.GoToStore(store.storeId, StoreNavPages.Checkout);
|
||||
s.SetCheckbox(s, "LightningAmountInSatoshi", true);
|
||||
var command = s.Driver.FindElement(By.Name("command"));
|
||||
|
||||
command.ForceClick();
|
||||
var invoiceId = s.CreateInvoice(store.storeName, 10, "USD", "a@g.com");
|
||||
s.GoToInvoiceCheckout(invoiceId);
|
||||
Assert.Contains("Sats", s.Driver.FindElement(By.ClassName("payment__currencies_noborder")).Text);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,42 +27,20 @@ namespace BTCPayServer.Tests
|
||||
{
|
||||
public class SeleniumTester : IDisposable
|
||||
{
|
||||
private IWebDriver _Driver;
|
||||
public IWebDriver Driver
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_Driver == null)
|
||||
{
|
||||
Start();
|
||||
}
|
||||
return _Driver;
|
||||
}
|
||||
}
|
||||
private ServerTester _Server;
|
||||
public ServerTester Server
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_Server == null)
|
||||
{
|
||||
_Server = ServerTester.Create("Default Scope");
|
||||
Start();
|
||||
}
|
||||
return _Server;
|
||||
}
|
||||
}
|
||||
public IWebDriver Driver { get; set; }
|
||||
public ServerTester Server { get; set; }
|
||||
|
||||
public static SeleniumTester Create([CallerMemberNameAttribute] string scope = null)
|
||||
{
|
||||
var server = ServerTester.Create(scope);
|
||||
return new SeleniumTester()
|
||||
{
|
||||
_Server = ServerTester.Create(scope)
|
||||
Server = server
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
void Start()
|
||||
public void Start()
|
||||
{
|
||||
Server.Start();
|
||||
ChromeOptions options = new ChromeOptions();
|
||||
@ -78,7 +56,7 @@ namespace BTCPayServer.Tests
|
||||
{
|
||||
options.AddArgument("no-sandbox");
|
||||
}
|
||||
_Driver = new ChromeDriver(Server.PayTester.InContainer ? "/usr/bin" : Directory.GetCurrentDirectory(), options);
|
||||
Driver = new ChromeDriver(Server.PayTester.InContainer ? "/usr/bin" : Directory.GetCurrentDirectory(), options);
|
||||
if (isDebug)
|
||||
{
|
||||
//when running locally, depending on your resolution, the website may go into mobile responsive mode and screw with navigation of tests
|
||||
@ -99,10 +77,7 @@ namespace BTCPayServer.Tests
|
||||
|
||||
public string RegisterNewUser(bool isAdmin = false)
|
||||
{
|
||||
GoToHome();
|
||||
if (Driver.PageSource.Contains("id=\"Logout\""))
|
||||
Logout();
|
||||
var usr = RandomUtils.GetUInt256().ToString().Substring(20) + "@a.com";
|
||||
var usr = RandomUtils.GetUInt256().ToString() + "@a.com";
|
||||
Driver.FindElement(By.Id("Register")).Click();
|
||||
Driver.FindElement(By.Id("Email")).SendKeys(usr);
|
||||
Driver.FindElement(By.Id("Password")).SendKeys("123456");
|
||||
|
@ -12,72 +12,79 @@ using System.Threading.Tasks;
|
||||
namespace BTCPayServer.Tests
|
||||
{
|
||||
[Trait("Selenium", "Selenium")]
|
||||
[Collection("Selenium collection")]
|
||||
public class ChromeTests
|
||||
{
|
||||
public SeleniumTester SeleniumTester { get; }
|
||||
|
||||
public ChromeTests(ITestOutputHelper helper, SeleniumTester seleniumTester)
|
||||
public ChromeTests(ITestOutputHelper helper)
|
||||
{
|
||||
Logs.Tester = new XUnitLog(helper) { Name = "Tests" };
|
||||
Logs.LogProvider = new XUnitLogProvider(helper);
|
||||
SeleniumTester = seleniumTester;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanNavigateServerSettings()
|
||||
{
|
||||
SeleniumTester.RegisterNewUser(true);
|
||||
SeleniumTester.Driver.FindElement(By.Id("ServerSettings")).Click();
|
||||
SeleniumTester.Driver.AssertNoError();
|
||||
SeleniumTester.ClickOnAllSideMenus();
|
||||
using (var s = SeleniumTester.Create())
|
||||
{
|
||||
s.Start();
|
||||
s.RegisterNewUser(true);
|
||||
s.Driver.FindElement(By.Id("ServerSettings")).Click();
|
||||
s.Driver.AssertNoError();
|
||||
s.ClickOnAllSideMenus();
|
||||
s.Driver.Quit();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NewUserLogin()
|
||||
{
|
||||
//Register & Log Out
|
||||
var email = SeleniumTester.RegisterNewUser();
|
||||
SeleniumTester.Driver.FindElement(By.Id("Logout")).Click();
|
||||
SeleniumTester.Driver.AssertNoError();
|
||||
SeleniumTester.Driver.FindElement(By.Id("Login")).Click();
|
||||
SeleniumTester.Driver.AssertNoError();
|
||||
using (var s = SeleniumTester.Create())
|
||||
{
|
||||
s.Start();
|
||||
//Register & Log Out
|
||||
var email = s.RegisterNewUser();
|
||||
s.Driver.FindElement(By.Id("Logout")).Click();
|
||||
s.Driver.AssertNoError();
|
||||
s.Driver.FindElement(By.Id("Login")).Click();
|
||||
s.Driver.AssertNoError();
|
||||
|
||||
SeleniumTester.Driver.Navigate().GoToUrl(SeleniumTester.Link("/invoices"));
|
||||
Assert.Contains("ReturnUrl=%2Finvoices", SeleniumTester.Driver.Url);
|
||||
s.Driver.Navigate().GoToUrl(s.Link("/invoices"));
|
||||
Assert.Contains("ReturnUrl=%2Finvoices", s.Driver.Url);
|
||||
|
||||
// We should be redirected to login
|
||||
//Same User Can Log Back In
|
||||
SeleniumTester.Driver.FindElement(By.Id("Email")).SendKeys(email);
|
||||
SeleniumTester.Driver.FindElement(By.Id("Password")).SendKeys("123456");
|
||||
SeleniumTester.Driver.FindElement(By.Id("LoginButton")).Click();
|
||||
// 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
|
||||
Assert.EndsWith("/invoices", SeleniumTester.Driver.Url);
|
||||
// We should be redirected to invoice
|
||||
Assert.EndsWith("/invoices", s.Driver.Url);
|
||||
|
||||
// Should not be able to reach server settings
|
||||
SeleniumTester.Driver.Navigate().GoToUrl(SeleniumTester.Link("/server/users"));
|
||||
Assert.Contains("ReturnUrl=%2Fserver%2Fusers", SeleniumTester.Driver.Url);
|
||||
// Should not be able to reach server settings
|
||||
s.Driver.Navigate().GoToUrl(s.Link("/server/users"));
|
||||
Assert.Contains("ReturnUrl=%2Fserver%2Fusers", s.Driver.Url);
|
||||
|
||||
//Change Password & Log Out
|
||||
SeleniumTester.Driver.FindElement(By.Id("MySettings")).Click();
|
||||
SeleniumTester.Driver.FindElement(By.Id("ChangePassword")).Click();
|
||||
SeleniumTester.Driver.FindElement(By.Id("OldPassword")).SendKeys("123456");
|
||||
SeleniumTester.Driver.FindElement(By.Id("NewPassword")).SendKeys("abc???");
|
||||
SeleniumTester.Driver.FindElement(By.Id("ConfirmPassword")).SendKeys("abc???");
|
||||
SeleniumTester.Driver.FindElement(By.Id("UpdatePassword")).Click();
|
||||
SeleniumTester.Driver.FindElement(By.Id("Logout")).Click();
|
||||
SeleniumTester.Driver.AssertNoError();
|
||||
//Change Password & Log Out
|
||||
s.Driver.FindElement(By.Id("MySettings")).Click();
|
||||
s.Driver.FindElement(By.Id("ChangePassword")).Click();
|
||||
s.Driver.FindElement(By.Id("OldPassword")).SendKeys("123456");
|
||||
s.Driver.FindElement(By.Id("NewPassword")).SendKeys("abc???");
|
||||
s.Driver.FindElement(By.Id("ConfirmPassword")).SendKeys("abc???");
|
||||
s.Driver.FindElement(By.Id("UpdatePassword")).Click();
|
||||
s.Driver.FindElement(By.Id("Logout")).Click();
|
||||
s.Driver.AssertNoError();
|
||||
|
||||
//Log In With New Password
|
||||
SeleniumTester.Driver.FindElement(By.Id("Login")).Click();
|
||||
SeleniumTester.Driver.FindElement(By.Id("Email")).SendKeys(email);
|
||||
SeleniumTester.Driver.FindElement(By.Id("Password")).SendKeys("abc???");
|
||||
SeleniumTester.Driver.FindElement(By.Id("LoginButton")).Click();
|
||||
Assert.True(SeleniumTester.Driver.PageSource.Contains("Stores"), "Can't Access Stores");
|
||||
//Log In With New Password
|
||||
s.Driver.FindElement(By.Id("Login")).Click();
|
||||
s.Driver.FindElement(By.Id("Email")).SendKeys(email);
|
||||
s.Driver.FindElement(By.Id("Password")).SendKeys("abc???");
|
||||
s.Driver.FindElement(By.Id("LoginButton")).Click();
|
||||
Assert.True(s.Driver.PageSource.Contains("Stores"), "Can't Access Stores");
|
||||
|
||||
SeleniumTester.Driver.FindElement(By.Id("MySettings")).Click();
|
||||
SeleniumTester.ClickOnAllSideMenus();
|
||||
s.Driver.FindElement(By.Id("MySettings")).Click();
|
||||
s.ClickOnAllSideMenus();
|
||||
|
||||
s.Driver.Quit();
|
||||
}
|
||||
}
|
||||
|
||||
static void LogIn(SeleniumTester s, string email)
|
||||
@ -91,239 +98,270 @@ namespace BTCPayServer.Tests
|
||||
[Fact]
|
||||
public async Task CanUseSSHService()
|
||||
{
|
||||
var alice = SeleniumTester.RegisterNewUser(isAdmin: true);
|
||||
SeleniumTester.Driver.Navigate().GoToUrl(SeleniumTester.Link("/server/services"));
|
||||
Assert.Contains("server/services/ssh", SeleniumTester.Driver.PageSource);
|
||||
using (var client = await SeleniumTester.Server.PayTester.GetService<BTCPayServer.Configuration.BTCPayServerOptions>().SSHSettings.ConnectAsync())
|
||||
using (var s = SeleniumTester.Create())
|
||||
{
|
||||
var result = await client.RunBash("echo hello");
|
||||
Assert.Equal(string.Empty, result.Error);
|
||||
Assert.Equal("hello\n", result.Output);
|
||||
Assert.Equal(0, result.ExitStatus);
|
||||
s.Start();
|
||||
var alice = 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<BTCPayServer.Configuration.BTCPayServerOptions>().SSHSettings.ConnectAsync())
|
||||
{
|
||||
var result = await client.RunBash("echo hello");
|
||||
Assert.Equal(string.Empty, result.Error);
|
||||
Assert.Equal("hello\n", result.Output);
|
||||
Assert.Equal(0, result.ExitStatus);
|
||||
}
|
||||
s.Driver.Navigate().GoToUrl(s.Link("/server/services/ssh"));
|
||||
s.Driver.AssertNoError();
|
||||
}
|
||||
SeleniumTester.Driver.Navigate().GoToUrl(SeleniumTester.Link("/server/services/ssh"));
|
||||
SeleniumTester.Driver.AssertNoError();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanUseDynamicDns()
|
||||
{
|
||||
var alice = SeleniumTester.RegisterNewUser(isAdmin: true);
|
||||
SeleniumTester.Driver.Navigate().GoToUrl(SeleniumTester.Link("/server/services"));
|
||||
Assert.Contains("Dynamic DNS", SeleniumTester.Driver.PageSource);
|
||||
|
||||
SeleniumTester.Driver.Navigate().GoToUrl(SeleniumTester.Link("/server/services/dynamic-dns"));
|
||||
SeleniumTester.Driver.AssertNoError();
|
||||
if (SeleniumTester.Driver.PageSource.Contains("pouet.hello.com"))
|
||||
using (var s = SeleniumTester.Create())
|
||||
{
|
||||
// Cleanup old test run
|
||||
SeleniumTester.Driver.Navigate().GoToUrl(SeleniumTester.Link("/server/services/dynamic-dns/pouet.hello.com/delete"));
|
||||
SeleniumTester.Driver.FindElement(By.Id("continue")).Click();
|
||||
s.Start();
|
||||
var alice = 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"))
|
||||
{
|
||||
// Cleanup old test run
|
||||
s.Driver.Navigate().GoToUrl(s.Link("/server/services/dynamic-dns/pouet.hello.com/delete"));
|
||||
s.Driver.FindElement(By.Id("continue")).Click();
|
||||
}
|
||||
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("continue")).Click();
|
||||
s.Driver.AssertNoError();
|
||||
|
||||
Assert.DoesNotContain("/server/services/dynamic-dns/pouet.hello.com/delete", s.Driver.PageSource);
|
||||
}
|
||||
SeleniumTester.Driver.FindElement(By.Id("AddDynamicDNS")).Click();
|
||||
SeleniumTester.Driver.AssertNoError();
|
||||
// We will just cheat for test purposes by only querying the server
|
||||
SeleniumTester.Driver.FindElement(By.Id("ServiceUrl")).SendKeys(SeleniumTester.Link("/"));
|
||||
SeleniumTester.Driver.FindElement(By.Id("Settings_Hostname")).SendKeys("pouet.hello.com");
|
||||
SeleniumTester.Driver.FindElement(By.Id("Settings_Login")).SendKeys("MyLog");
|
||||
SeleniumTester.Driver.FindElement(By.Id("Settings_Password")).SendKeys("MyLog" + Keys.Enter);
|
||||
SeleniumTester.Driver.AssertNoError();
|
||||
Assert.Contains("The Dynamic DNS has been successfully queried", SeleniumTester.Driver.PageSource);
|
||||
Assert.EndsWith("/server/services/dynamic-dns", SeleniumTester.Driver.Url);
|
||||
|
||||
// Try to do the same thing should fail (hostname already exists)
|
||||
SeleniumTester.Driver.FindElement(By.Id("AddDynamicDNS")).Click();
|
||||
SeleniumTester.Driver.AssertNoError();
|
||||
SeleniumTester.Driver.FindElement(By.Id("ServiceUrl")).SendKeys(SeleniumTester.Link("/"));
|
||||
SeleniumTester.Driver.FindElement(By.Id("Settings_Hostname")).SendKeys("pouet.hello.com");
|
||||
SeleniumTester.Driver.FindElement(By.Id("Settings_Login")).SendKeys("MyLog");
|
||||
SeleniumTester.Driver.FindElement(By.Id("Settings_Password")).SendKeys("MyLog" + Keys.Enter);
|
||||
SeleniumTester.Driver.AssertNoError();
|
||||
Assert.Contains("This hostname already exists", SeleniumTester.Driver.PageSource);
|
||||
|
||||
// Delete it
|
||||
SeleniumTester.Driver.Navigate().GoToUrl(SeleniumTester.Link("/server/services/dynamic-dns"));
|
||||
Assert.Contains("/server/services/dynamic-dns/pouet.hello.com/delete", SeleniumTester.Driver.PageSource);
|
||||
SeleniumTester.Driver.Navigate().GoToUrl(SeleniumTester.Link("/server/services/dynamic-dns/pouet.hello.com/delete"));
|
||||
SeleniumTester.Driver.FindElement(By.Id("continue")).Click();
|
||||
SeleniumTester.Driver.AssertNoError();
|
||||
|
||||
Assert.DoesNotContain("/server/services/dynamic-dns/pouet.hello.com/delete", SeleniumTester.Driver.PageSource);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanCreateStores()
|
||||
{
|
||||
var alice = SeleniumTester.RegisterNewUser();
|
||||
var store = SeleniumTester.CreateNewStore().storeName;
|
||||
SeleniumTester.AddDerivationScheme();
|
||||
SeleniumTester.Driver.AssertNoError();
|
||||
Assert.Contains(store, SeleniumTester.Driver.PageSource);
|
||||
var storeUrl = SeleniumTester.Driver.Url;
|
||||
SeleniumTester.ClickOnAllSideMenus();
|
||||
SeleniumTester.GoToInvoices();
|
||||
SeleniumTester.CreateInvoice(store);
|
||||
SeleniumTester.Driver.FindElement(By.ClassName("invoice-details-link")).Click();
|
||||
var invoiceUrl = SeleniumTester.Driver.Url;
|
||||
using (var s = SeleniumTester.Create())
|
||||
{
|
||||
s.Start();
|
||||
var alice = s.RegisterNewUser();
|
||||
var store = s.CreateNewStore().storeName;
|
||||
s.AddDerivationScheme();
|
||||
s.Driver.AssertNoError();
|
||||
Assert.Contains(store, s.Driver.PageSource);
|
||||
var storeUrl = s.Driver.Url;
|
||||
s.ClickOnAllSideMenus();
|
||||
s.GoToInvoices();
|
||||
s.CreateInvoice(store);
|
||||
s.Driver.FindElement(By.ClassName("invoice-details-link")).Click();
|
||||
var invoiceUrl = s.Driver.Url;
|
||||
|
||||
// When logout we should not be able to access store and invoice details
|
||||
SeleniumTester.Driver.FindElement(By.Id("Logout")).Click();
|
||||
SeleniumTester.Driver.Navigate().GoToUrl(storeUrl);
|
||||
Assert.Contains("ReturnUrl", SeleniumTester.Driver.Url);
|
||||
SeleniumTester.Driver.Navigate().GoToUrl(invoiceUrl);
|
||||
Assert.Contains("ReturnUrl", SeleniumTester.Driver.Url);
|
||||
// When logout we should not be able to access store and invoice details
|
||||
s.Driver.FindElement(By.Id("Logout")).Click();
|
||||
s.Driver.Navigate().GoToUrl(storeUrl);
|
||||
Assert.Contains("ReturnUrl", s.Driver.Url);
|
||||
s.Driver.Navigate().GoToUrl(invoiceUrl);
|
||||
Assert.Contains("ReturnUrl", s.Driver.Url);
|
||||
|
||||
// When logged we should not be able to access store and invoice details
|
||||
var bob = SeleniumTester.RegisterNewUser();
|
||||
SeleniumTester.Driver.Navigate().GoToUrl(storeUrl);
|
||||
Assert.Contains("ReturnUrl", SeleniumTester.Driver.Url);
|
||||
SeleniumTester.Driver.Navigate().GoToUrl(invoiceUrl);
|
||||
SeleniumTester.AssertNotFound();
|
||||
SeleniumTester.GoToHome();
|
||||
SeleniumTester.Logout();
|
||||
// When logged we should not be able to access store and invoice details
|
||||
var bob = s.RegisterNewUser();
|
||||
s.Driver.Navigate().GoToUrl(storeUrl);
|
||||
Assert.Contains("ReturnUrl", s.Driver.Url);
|
||||
s.Driver.Navigate().GoToUrl(invoiceUrl);
|
||||
s.AssertNotFound();
|
||||
s.GoToHome();
|
||||
s.Logout();
|
||||
|
||||
// Let's add Bob as a guest to alice's store
|
||||
LogIn(SeleniumTester, alice);
|
||||
SeleniumTester.Driver.Navigate().GoToUrl(storeUrl + "/users");
|
||||
SeleniumTester.Driver.FindElement(By.Id("Email")).SendKeys(bob + Keys.Enter);
|
||||
Assert.Contains("User added successfully", SeleniumTester.Driver.PageSource);
|
||||
SeleniumTester.Logout();
|
||||
// Let's add Bob as a guest to alice's store
|
||||
LogIn(s, alice);
|
||||
s.Driver.Navigate().GoToUrl(storeUrl + "/users");
|
||||
s.Driver.FindElement(By.Id("Email")).SendKeys(bob + Keys.Enter);
|
||||
Assert.Contains("User added successfully", s.Driver.PageSource);
|
||||
s.Logout();
|
||||
|
||||
// Bob should not have access to store, but should have access to invoice
|
||||
LogIn(SeleniumTester, bob);
|
||||
SeleniumTester.Driver.Navigate().GoToUrl(storeUrl);
|
||||
Assert.Contains("ReturnUrl", SeleniumTester.Driver.Url);
|
||||
SeleniumTester.Driver.Navigate().GoToUrl(invoiceUrl);
|
||||
SeleniumTester.Driver.AssertNoError();
|
||||
// Bob should not have access to store, but should have access to invoice
|
||||
LogIn(s, bob);
|
||||
s.Driver.Navigate().GoToUrl(storeUrl);
|
||||
Assert.Contains("ReturnUrl", s.Driver.Url);
|
||||
s.Driver.Navigate().GoToUrl(invoiceUrl);
|
||||
s.Driver.AssertNoError();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
[Fact]
|
||||
public void CanCreateAppPoS()
|
||||
{
|
||||
SeleniumTester.RegisterNewUser();
|
||||
var store = SeleniumTester.CreateNewStore();
|
||||
using (var s = SeleniumTester.Create())
|
||||
{
|
||||
s.Start();
|
||||
s.RegisterNewUser();
|
||||
var store = s.CreateNewStore();
|
||||
|
||||
SeleniumTester.Driver.FindElement(By.Id("Apps")).Click();
|
||||
SeleniumTester.Driver.FindElement(By.Id("CreateNewApp")).Click();
|
||||
SeleniumTester.Driver.FindElement(By.Name("Name")).SendKeys("PoS" + Guid.NewGuid());
|
||||
SeleniumTester.Driver.FindElement(By.Id("SelectedAppType")).SendKeys("PointOfSale" + Keys.Enter);
|
||||
SeleniumTester.Driver.FindElement(By.Id("SelectedStore")).SendKeys(store + Keys.Enter);
|
||||
SeleniumTester.Driver.FindElement(By.Id("Create")).Click();
|
||||
SeleniumTester.Driver.FindElement(By.Id("EnableShoppingCart")).Click();
|
||||
SeleniumTester.Driver.FindElement(By.Id("SaveSettings")).ForceClick();
|
||||
SeleniumTester.Driver.FindElement(By.Id("ViewApp")).ForceClick();
|
||||
SeleniumTester.Driver.SwitchTo().Window(SeleniumTester.Driver.WindowHandles.Last());
|
||||
Assert.True(SeleniumTester.Driver.PageSource.Contains("Tea shop"), "Unable to create PoS");
|
||||
s.Driver.FindElement(By.Id("Apps")).Click();
|
||||
s.Driver.FindElement(By.Id("CreateNewApp")).Click();
|
||||
s.Driver.FindElement(By.Name("Name")).SendKeys("PoS" + Guid.NewGuid());
|
||||
s.Driver.FindElement(By.Id("SelectedAppType")).SendKeys("PointOfSale" + Keys.Enter);
|
||||
s.Driver.FindElement(By.Id("SelectedStore")).SendKeys(store + Keys.Enter);
|
||||
s.Driver.FindElement(By.Id("Create")).Click();
|
||||
s.Driver.FindElement(By.Id("EnableShoppingCart")).Click();
|
||||
s.Driver.FindElement(By.Id("SaveSettings")).ForceClick();
|
||||
s.Driver.FindElement(By.Id("ViewApp")).ForceClick();
|
||||
s.Driver.SwitchTo().Window(s.Driver.WindowHandles.Last());
|
||||
Assert.True(s.Driver.PageSource.Contains("Tea shop"), "Unable to create PoS");
|
||||
s.Driver.Quit();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanCreateAppCF()
|
||||
{
|
||||
SeleniumTester.RegisterNewUser();
|
||||
var store = SeleniumTester.CreateNewStore();
|
||||
SeleniumTester.AddDerivationScheme();
|
||||
using (var s = SeleniumTester.Create())
|
||||
{
|
||||
s.Start();
|
||||
s.RegisterNewUser();
|
||||
var store = s.CreateNewStore();
|
||||
s.AddDerivationScheme();
|
||||
|
||||
SeleniumTester.Driver.FindElement(By.Id("Apps")).Click();
|
||||
SeleniumTester.Driver.FindElement(By.Id("CreateNewApp")).Click();
|
||||
SeleniumTester.Driver.FindElement(By.Name("Name")).SendKeys("CF" + Guid.NewGuid());
|
||||
SeleniumTester.Driver.FindElement(By.Id("SelectedAppType")).SendKeys("Crowdfund" + Keys.Enter);
|
||||
SeleniumTester.Driver.FindElement(By.Id("SelectedStore")).SendKeys(store + Keys.Enter);
|
||||
SeleniumTester.Driver.FindElement(By.Id("Create")).Click();
|
||||
SeleniumTester.Driver.FindElement(By.Id("Title")).SendKeys("Kukkstarter");
|
||||
SeleniumTester.Driver.FindElement(By.CssSelector("div.note-editable.card-block")).SendKeys("1BTC = 1BTC");
|
||||
SeleniumTester.Driver.FindElement(By.Id("TargetCurrency")).SendKeys("JPY");
|
||||
SeleniumTester.Driver.FindElement(By.Id("TargetAmount")).SendKeys("700");
|
||||
SeleniumTester.Driver.FindElement(By.Id("SaveSettings")).ForceClick();
|
||||
SeleniumTester.Driver.FindElement(By.Id("ViewApp")).ForceClick();
|
||||
SeleniumTester.Driver.SwitchTo().Window(SeleniumTester.Driver.WindowHandles.Last());
|
||||
Assert.True(SeleniumTester.Driver.PageSource.Contains("Currently Active!"), "Unable to create CF");
|
||||
s.Driver.FindElement(By.Id("Apps")).Click();
|
||||
s.Driver.FindElement(By.Id("CreateNewApp")).Click();
|
||||
s.Driver.FindElement(By.Name("Name")).SendKeys("CF" + Guid.NewGuid());
|
||||
s.Driver.FindElement(By.Id("SelectedAppType")).SendKeys("Crowdfund" + Keys.Enter);
|
||||
s.Driver.FindElement(By.Id("SelectedStore")).SendKeys(store + Keys.Enter);
|
||||
s.Driver.FindElement(By.Id("Create")).Click();
|
||||
s.Driver.FindElement(By.Id("Title")).SendKeys("Kukkstarter");
|
||||
s.Driver.FindElement(By.CssSelector("div.note-editable.card-block")).SendKeys("1BTC = 1BTC");
|
||||
s.Driver.FindElement(By.Id("TargetCurrency")).SendKeys("JPY");
|
||||
s.Driver.FindElement(By.Id("TargetAmount")).SendKeys("700");
|
||||
s.Driver.FindElement(By.Id("SaveSettings")).ForceClick();
|
||||
s.Driver.FindElement(By.Id("ViewApp")).ForceClick();
|
||||
s.Driver.SwitchTo().Window(s.Driver.WindowHandles.Last());
|
||||
Assert.True(s.Driver.PageSource.Contains("Currently Active!"), "Unable to create CF");
|
||||
s.Driver.Quit();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanCreatePayRequest()
|
||||
{
|
||||
SeleniumTester.RegisterNewUser();
|
||||
SeleniumTester.CreateNewStore();
|
||||
SeleniumTester.AddDerivationScheme();
|
||||
using (var s = SeleniumTester.Create())
|
||||
{
|
||||
s.Start();
|
||||
s.RegisterNewUser();
|
||||
s.CreateNewStore();
|
||||
s.AddDerivationScheme();
|
||||
|
||||
SeleniumTester.Driver.FindElement(By.Id("PaymentRequests")).Click();
|
||||
SeleniumTester.Driver.FindElement(By.Id("CreatePaymentRequest")).Click();
|
||||
SeleniumTester.Driver.FindElement(By.Id("Title")).SendKeys("Pay123");
|
||||
SeleniumTester.Driver.FindElement(By.Id("Amount")).SendKeys("700");
|
||||
SeleniumTester.Driver.FindElement(By.Id("Currency")).SendKeys("BTC");
|
||||
SeleniumTester.Driver.FindElement(By.Id("SaveButton")).ForceClick();
|
||||
SeleniumTester.Driver.FindElement(By.Name("ViewAppButton")).SendKeys(Keys.Return);
|
||||
SeleniumTester.Driver.SwitchTo().Window(SeleniumTester.Driver.WindowHandles.Last());
|
||||
Assert.True(SeleniumTester.Driver.PageSource.Contains("Amount due"), "Unable to create Payment Request");
|
||||
s.Driver.FindElement(By.Id("PaymentRequests")).Click();
|
||||
s.Driver.FindElement(By.Id("CreatePaymentRequest")).Click();
|
||||
s.Driver.FindElement(By.Id("Title")).SendKeys("Pay123");
|
||||
s.Driver.FindElement(By.Id("Amount")).SendKeys("700");
|
||||
s.Driver.FindElement(By.Id("Currency")).SendKeys("BTC");
|
||||
s.Driver.FindElement(By.Id("SaveButton")).ForceClick();
|
||||
s.Driver.FindElement(By.Name("ViewAppButton")).SendKeys(Keys.Return);
|
||||
s.Driver.SwitchTo().Window(s.Driver.WindowHandles.Last());
|
||||
Assert.True(s.Driver.PageSource.Contains("Amount due"), "Unable to create Payment Request");
|
||||
s.Driver.Quit();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanManageWallet()
|
||||
{
|
||||
SeleniumTester.RegisterNewUser();
|
||||
SeleniumTester.CreateNewStore();
|
||||
|
||||
// In this test, we try to spend from a manual seed. We import the xpub 49'/0'/0', then try to use the seed
|
||||
// to sign the transaction
|
||||
var mnemonic = "usage fever hen zero slide mammal silent heavy donate budget pulse say brain thank sausage brand craft about save attract muffin advance illegal cabbage";
|
||||
var root = new Mnemonic(mnemonic).DeriveExtKey();
|
||||
SeleniumTester.AddDerivationScheme("BTC", "ypub6WWc2gWwHbdnAAyJDnR4SPL1phRh7REqrPBfZeizaQ1EmTshieRXJC3Z5YoU4wkcdKHEjQGkh6AYEzCQC1Kz3DNaWSwdc1pc8416hAjzqyD");
|
||||
var tx = SeleniumTester.Server.ExplorerNode.SendToAddress(BitcoinAddress.Create("bcrt1qmxg8fgnmkp354vhe78j6sr4ut64tyz2xyejel4", Network.RegTest), Money.Coins(3.0m));
|
||||
SeleniumTester.Server.ExplorerNode.Generate(1);
|
||||
|
||||
SeleniumTester.Driver.FindElement(By.Id("Wallets")).Click();
|
||||
SeleniumTester.Driver.FindElement(By.LinkText("Manage")).Click();
|
||||
|
||||
SeleniumTester.ClickOnAllSideMenus();
|
||||
|
||||
// We setup the fingerprint and the account key path
|
||||
SeleniumTester.Driver.FindElement(By.Id("WalletSettings")).ForceClick();
|
||||
SeleniumTester.Driver.FindElement(By.Id("AccountKeys_0__MasterFingerprint")).SendKeys("8bafd160");
|
||||
SeleniumTester.Driver.FindElement(By.Id("AccountKeys_0__AccountKeyPath")).SendKeys("m/49'/0'/0'" + Keys.Enter);
|
||||
|
||||
// Check the tx sent earlier arrived
|
||||
SeleniumTester.Driver.FindElement(By.Id("WalletTransactions")).ForceClick();
|
||||
var walletTransactionLink = SeleniumTester.Driver.Url;
|
||||
Assert.Contains(tx.ToString(), SeleniumTester.Driver.PageSource);
|
||||
|
||||
|
||||
void SignWith(string signingSource)
|
||||
using (var s = SeleniumTester.Create())
|
||||
{
|
||||
// Send to bob
|
||||
SeleniumTester.Driver.FindElement(By.Id("WalletSend")).Click();
|
||||
var bob = new Key().PubKey.Hash.GetAddress(Network.RegTest);
|
||||
SetTransactionOutput(0, bob, 1);
|
||||
SeleniumTester.Driver.ScrollTo(By.Id("SendMenu"));
|
||||
SeleniumTester.Driver.FindElement(By.Id("SendMenu")).ForceClick();
|
||||
SeleniumTester.Driver.FindElement(By.CssSelector("button[value=seed]")).Click();
|
||||
s.Start();
|
||||
s.RegisterNewUser();
|
||||
s.CreateNewStore();
|
||||
|
||||
// Input the seed
|
||||
SeleniumTester.Driver.FindElement(By.Id("SeedOrKey")).SendKeys(signingSource + Keys.Enter);
|
||||
// In this test, we try to spend from a manual seed. We import the xpub 49'/0'/0', then try to use the seed
|
||||
// to sign the transaction
|
||||
var mnemonic = "usage fever hen zero slide mammal silent heavy donate budget pulse say brain thank sausage brand craft about save attract muffin advance illegal cabbage";
|
||||
var root = new Mnemonic(mnemonic).DeriveExtKey();
|
||||
s.AddDerivationScheme("BTC", "ypub6WWc2gWwHbdnAAyJDnR4SPL1phRh7REqrPBfZeizaQ1EmTshieRXJC3Z5YoU4wkcdKHEjQGkh6AYEzCQC1Kz3DNaWSwdc1pc8416hAjzqyD");
|
||||
var tx = s.Server.ExplorerNode.SendToAddress(BitcoinAddress.Create("bcrt1qmxg8fgnmkp354vhe78j6sr4ut64tyz2xyejel4", Network.RegTest), Money.Coins(3.0m));
|
||||
s.Server.ExplorerNode.Generate(1);
|
||||
|
||||
// Broadcast
|
||||
Assert.Contains(bob.ToString(), SeleniumTester.Driver.PageSource);
|
||||
Assert.Contains("1.00000000", SeleniumTester.Driver.PageSource);
|
||||
SeleniumTester.Driver.FindElement(By.CssSelector("button[value=broadcast]")).ForceClick();
|
||||
Assert.Equal(walletTransactionLink, SeleniumTester.Driver.Url);
|
||||
}
|
||||
s.Driver.FindElement(By.Id("Wallets")).Click();
|
||||
s.Driver.FindElement(By.LinkText("Manage")).Click();
|
||||
|
||||
void SetTransactionOutput(int index, BitcoinAddress dest, decimal amount, bool subtract = false)
|
||||
{
|
||||
SeleniumTester.Driver.FindElement(By.Id($"Outputs_{index}__DestinationAddress")).SendKeys(dest.ToString());
|
||||
var amountElement = SeleniumTester.Driver.FindElement(By.Id($"Outputs_{index}__Amount"));
|
||||
amountElement.Clear();
|
||||
amountElement.SendKeys(amount.ToString());
|
||||
var checkboxElement = SeleniumTester.Driver.FindElement(By.Id($"Outputs_{index}__SubtractFeesFromOutput"));
|
||||
if (checkboxElement.Selected != subtract)
|
||||
s.ClickOnAllSideMenus();
|
||||
|
||||
// We setup the fingerprint and the account key path
|
||||
s.Driver.FindElement(By.Id("WalletSettings")).ForceClick();
|
||||
s.Driver.FindElement(By.Id("AccountKeys_0__MasterFingerprint")).SendKeys("8bafd160");
|
||||
s.Driver.FindElement(By.Id("AccountKeys_0__AccountKeyPath")).SendKeys("m/49'/0'/0'" + Keys.Enter);
|
||||
|
||||
// Check the tx sent earlier arrived
|
||||
s.Driver.FindElement(By.Id("WalletTransactions")).ForceClick();
|
||||
var walletTransactionLink = s.Driver.Url;
|
||||
Assert.Contains(tx.ToString(), s.Driver.PageSource);
|
||||
|
||||
|
||||
void SignWith(string signingSource)
|
||||
{
|
||||
checkboxElement.Click();
|
||||
// Send to bob
|
||||
s.Driver.FindElement(By.Id("WalletSend")).Click();
|
||||
var bob = new Key().PubKey.Hash.GetAddress(Network.RegTest);
|
||||
SetTransactionOutput(0, bob, 1);
|
||||
s.Driver.ScrollTo(By.Id("SendMenu"));
|
||||
s.Driver.FindElement(By.Id("SendMenu")).ForceClick();
|
||||
s.Driver.FindElement(By.CssSelector("button[value=seed]")).Click();
|
||||
|
||||
// Input the seed
|
||||
s.Driver.FindElement(By.Id("SeedOrKey")).SendKeys(signingSource + Keys.Enter);
|
||||
|
||||
// Broadcast
|
||||
Assert.Contains(bob.ToString(), s.Driver.PageSource);
|
||||
Assert.Contains("1.00000000", s.Driver.PageSource);
|
||||
s.Driver.FindElement(By.CssSelector("button[value=broadcast]")).ForceClick();
|
||||
Assert.Equal(walletTransactionLink, s.Driver.Url);
|
||||
}
|
||||
|
||||
void SetTransactionOutput(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());
|
||||
var checkboxElement = s.Driver.FindElement(By.Id($"Outputs_{index}__SubtractFeesFromOutput"));
|
||||
if (checkboxElement.Selected != subtract)
|
||||
{
|
||||
checkboxElement.Click();
|
||||
}
|
||||
}
|
||||
SignWith(mnemonic);
|
||||
var accountKey = root.Derive(new KeyPath("m/49'/0'/0'")).GetWif(Network.RegTest).ToString();
|
||||
SignWith(accountKey);
|
||||
}
|
||||
SignWith(mnemonic);
|
||||
var accountKey = root.Derive(new KeyPath("m/49'/0'/0'")).GetWif(Network.RegTest).ToString();
|
||||
SignWith(accountKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace BTCPayServer.Tests
|
||||
{
|
||||
[CollectionDefinition("Selenium collection")]
|
||||
public class SeleniumCollection : ICollectionFixture<SeleniumTester>
|
||||
{
|
||||
// This class has no code, and is never created. Its purpose is simply
|
||||
// to be the place to apply [CollectionDefinition] and all the
|
||||
// ICollectionFixture<> interfaces.
|
||||
}
|
||||
}
|
@ -13,7 +13,6 @@ using BTCPayServer.Services.Invoices;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Rates;
|
||||
using NBitcoin;
|
||||
using System.Globalization;
|
||||
|
||||
namespace BTCPayServer.Payments.Lightning
|
||||
{
|
||||
@ -178,10 +177,10 @@ namespace BTCPayServer.Payments.Lightning
|
||||
if (storeBlob.LightningAmountInSatoshi && model.CryptoCode == "BTC" )
|
||||
{
|
||||
model.CryptoCode = "Sats";
|
||||
model.BtcDue = Money.Parse(model.BtcDue).ToUnit(MoneyUnit.Satoshi).ToString(CultureInfo.InvariantCulture);
|
||||
model.BtcPaid = Money.Parse(model.BtcPaid).ToUnit(MoneyUnit.Satoshi).ToString(CultureInfo.InvariantCulture);
|
||||
model.BtcDue = Money.Parse(model.BtcDue).ToUnit(MoneyUnit.Satoshi).ToString();
|
||||
model.BtcPaid = Money.Parse(model.BtcPaid).ToUnit(MoneyUnit.Satoshi).ToString();
|
||||
model.NetworkFee = new Money(model.NetworkFee, MoneyUnit.BTC).ToUnit(MoneyUnit.Satoshi);
|
||||
model.OrderAmount = Money.Parse(model.OrderAmount).ToUnit(MoneyUnit.Satoshi).ToString(CultureInfo.InvariantCulture);
|
||||
model.OrderAmount = Money.Parse(model.OrderAmount).ToUnit(MoneyUnit.Satoshi).ToString();
|
||||
}
|
||||
}
|
||||
public override string GetCryptoImage(PaymentMethodId paymentMethodId)
|
||||
|
Loading…
Reference in New Issue
Block a user