From 3107155ef29213a9a55f854b4e9998256e467b78 Mon Sep 17 00:00:00 2001 From: Kukks Date: Tue, 18 May 2021 14:13:11 +0200 Subject: [PATCH] wip --- BTCPayServer.Tests/PlayWrightExtensions.cs | 92 ++++++++++++ BTCPayServer.Tests/PlayWrightTester.cs | 86 ++++++----- BTCPayServer.Tests/PlayerwightExtensions.cs | 153 -------------------- 3 files changed, 138 insertions(+), 193 deletions(-) create mode 100644 BTCPayServer.Tests/PlayWrightExtensions.cs delete mode 100644 BTCPayServer.Tests/PlayerwightExtensions.cs diff --git a/BTCPayServer.Tests/PlayWrightExtensions.cs b/BTCPayServer.Tests/PlayWrightExtensions.cs new file mode 100644 index 000000000..295eba626 --- /dev/null +++ b/BTCPayServer.Tests/PlayWrightExtensions.cs @@ -0,0 +1,92 @@ +using System; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using BTCPayServer.Tests.Logging; +using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; +using OpenQA.Selenium; +using OpenQA.Selenium.Support.UI; +using PlaywrightSharp; +using Xunit; + +namespace BTCPayServer.Tests +{ + public static class PlayWrightExtensions + { + private static readonly JsonSerializerSettings JsonSettings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }; + public static string ToJson(this object o) => JsonConvert.SerializeObject(o, Formatting.None, JsonSettings); + + public static async Task LogIn(this PlayWrightTester s, string email) + { + await s.Page.TypeAsync("#Email", email); + await s.Page.TypeAsync("#Password", "123456"); + await s.Page.ClickAsync("#LoginButton"); + await s.Page.AssertNoError(); + } + + public static async Task AssertNoError(this IPage driver) + { + Assert.NotEmpty(await driver.QuerySelectorAllAsync("navbar-brand")); + + if ((await driver.GetContentAsync()).Contains("alert-danger")) + { + foreach (var dangerAlert in await driver.QuerySelectorAllAsync("alert-danger")) + Assert.False(await dangerAlert.IsVisibleAsync(), "No alert should be displayed"); + } + } + public static T AssertViewModel(this IActionResult result) + { + Assert.NotNull(result); + var vr = Assert.IsType(result); + return Assert.IsType(vr.Model); + } + public static async Task AssertViewModelAsync(this Task task) + { + var result = await task; + Assert.NotNull(result); + var vr = Assert.IsType(result); + return Assert.IsType(vr.Model); + } + + public static async Task AssertElementNotFound(this IPage driver, string selector) + { + DateTimeOffset now = DateTimeOffset.Now; + var wait = PlayWrightTester.ImplicitWait; + + while (DateTimeOffset.UtcNow - now < wait) + { + try + { + var webElement = await driver.QuerySelectorAsync(selector); + if (!await webElement.IsVisibleAsync()) + return; + } + catch (NoSuchWindowException) + { + return; + } + catch (NoSuchElementException) + { + return; + } + Thread.Sleep(50); + } + Assert.False(true, "Elements was found"); + } + + public static async Task SetCheckbox(this IPage driver, string selector, bool value) + { + var element = await driver.QuerySelectorAsync(selector); + if (value) + { + await element.CheckAsync(); + } + else + { + await element.UncheckAsync(); + } + } + } +} diff --git a/BTCPayServer.Tests/PlayWrightTester.cs b/BTCPayServer.Tests/PlayWrightTester.cs index 5effaf1e8..acbe263e9 100644 --- a/BTCPayServer.Tests/PlayWrightTester.cs +++ b/BTCPayServer.Tests/PlayWrightTester.cs @@ -237,9 +237,8 @@ namespace BTCPayServer.Tests public async Task ClickOnAllSideMenus() { - var links = await Task.WhenAll(Page - .QuerySelectorAllAsync(".nav .nav-link") - .ContinueWith(c => c.Result.SelectMany(handle => handle.GetAttributeAsync("href")))); + var links = await Task.WhenAll((await Page + .QuerySelectorAllAsync(".nav .nav-link")).Select(handle => handle.GetAttributeAsync("href"))); await Page.AssertNoError(); Assert.NotEmpty(links); foreach (var l in links) @@ -324,50 +323,57 @@ namespace BTCPayServer.Tests public async Task CreateInvoice(string storeName, decimal amount = 100, string currency = "USD", string refundEmail = "") { await GoToInvoices(); - Page.FindElement("#CreateNewInvoice")).Click(); - Page.FindElement("#Amount")).SendKeys(amount.ToString(CultureInfo.InvariantCulture)); - var currencyEl = Page.FindElement("#Currency")); - currencyEl.Clear(); - currencyEl.SendKeys(currency); - Page.FindElement("#BuyerEmail")).SendKeys(refundEmail); - Page.FindElement(By.Name("StoreId")).SendKeys(storeName); - Page.FindElement("#Create")).Click(); + await Page.ClickAsync("#CreateNewInvoice"); + await Page.TypeAsync("#Amount", amount.ToString(CultureInfo.InvariantCulture)); + var currencyEl = await Page.QuerySelectorAsync("#Currency"); + await currencyEl.FillAsync(""); + await currencyEl.TypeAsync(currency); + await Page.TypeAsync("#BuyerEmail",refundEmail); + await Page.TypeAsync("[name='StoreId']",storeName); + await Page.ClickAsync("#Create"); - var statusElement = FindAlertMessage(); - var id = statusElement.Text.Split(" ")[1]; + var statusElement = await FindAlertMessage(); + var id = (await statusElement.GetTextContentAsync()).Split(" ")[1]; return id; } public async Task FundStoreWallet(WalletId walletId = null, int coins = 1, decimal denomination = 1m) { walletId ??= WalletId; - GoToWallet(walletId, WalletsNavPages.Receive); - Page.FindElement("#generateButton")).Click(); - var addressStr = Page.FindElement("#address")).GetProperty("value"); + await GoToWallet(walletId, WalletsNavPages.Receive); + await Page.ClickAsync("#generateButton"); + var addressStr = await Page.GetAttributeAsync("#address", "value"); var address = BitcoinAddress.Create(addressStr, ((BTCPayNetwork)Server.NetworkProvider.GetNetwork(walletId.CryptoCode)).NBitcoinNetwork); for (var i = 0; i < coins; i++) { await Server.ExplorerNode.SendToAddressAsync(address, Money.Coins(denomination)); } } + + - public void PayInvoice(WalletId walletId, string invoiceId) + public async Task PayInvoice(WalletId walletId, string invoiceId) { - GoToInvoiceCheckout(invoiceId); - var bip21 = Page.FindElement(By.ClassName("payment__details__instruction__open-wallet__btn")) - .GetAttribute("href"); + await GoToInvoiceCheckout(invoiceId); + var bip21 = await Page.GetAttributeAsync(".payment__details__instruction__open-wallet__btn" , "href"); Assert.Contains($"{PayjoinClient.BIP21EndpointKey}", bip21); GoToWallet(walletId); - Page.FindElement("#bip21parse")).Click(); - Page.SwitchTo().Alert().SendKeys(bip21); - Page.SwitchTo().Alert().Accept(); - Page.FindElement("#SendMenu")).Click(); - Page.FindElement(By.CssSelector("button[value=nbx-seed]")).Click(); - Page.FindElement(By.CssSelector("button[value=broadcast]")).Click(); + var tcs = new TaskCompletionSource(); + Page.Dialog += async (_, dialog) => + { + Assert.Equal(dialog.Dialog.Type, DialogType.Prompt); + await dialog.Dialog.AcceptAsync(bip21); + tcs.SetResult(true); + }; + await Page.ClickAsync("#bip21parse"); + await tcs.Task; + await Page.ClickAsync("#SendMenu"); + await Page.ClickAsync("button[value=nbx-seed]"); + await Page.ClickAsync("button[value=broadcast]"); } - private void CheckForJSErrors() + private async Task CheckForJSErrors() { //wait for seleniun update: https://stackoverflow.com/questions/57520296/selenium-webdriver-3-141-0-driver-manage-logs-availablelogtypes-throwing-syste // var errorStrings = new List @@ -390,38 +396,38 @@ namespace BTCPayServer.Tests } - public void GoToWallet(WalletId walletId = null, WalletsNavPages navPages = WalletsNavPages.Send) + public async Task GoToWallet(WalletId walletId = null, WalletsNavPages navPages = WalletsNavPages.Send) { walletId ??= WalletId; - Page.Navigate().GoToUrl(new Uri(Server.PayTester.ServerUri, $"wallets/{walletId}")); + await Page.GoToAsync(new Uri(Server.PayTester.ServerUri, $"wallets/{walletId}").ToString()); if (navPages != WalletsNavPages.Transactions) { - Page.FindElement(By.Id($"Wallet{navPages}")).Click(); + await Page.ClickAsync($"#Wallet{navPages}"); } } - public void GoToUrl(string relativeUrl) + public async Task GoToUrl(string relativeUrl) { - Page.Navigate().GoToUrl(new Uri(Server.PayTester.ServerUri, relativeUrl)); + await Page.GoToAsync(new Uri(Server.PayTester.ServerUri, relativeUrl).ToString()); } - public void GoToServer(ServerNavPages navPages = ServerNavPages.Index) + public async Task GoToServer(ServerNavPages navPages = ServerNavPages.Index) { - Page.FindElement("#ServerSettings")).Click(); + await Page.ClickAsync("#ServerSettings"); if (navPages != ServerNavPages.Index) { - Page.FindElement(By.Id($"Server-{navPages}")).Click(); + await Page.ClickAsync($"#Server-{navPages}"); } } - public void GoToInvoice(string id) + public async Task GoToInvoice(string id) { - GoToInvoices(); - foreach (var el in Page.FindElements(By.ClassName("invoice-details-link"))) + await GoToInvoices(); + foreach (var el in await Page.QuerySelectorAllAsync(".invoice-details-link")) { - if (el.GetAttribute("href").Contains(id, StringComparison.OrdinalIgnoreCase)) + if ((await el.GetAttributeAsync("href")).Contains(id, StringComparison.OrdinalIgnoreCase)) { - el.Click(); + await el.ClickAsync(); break; } } diff --git a/BTCPayServer.Tests/PlayerwightExtensions.cs b/BTCPayServer.Tests/PlayerwightExtensions.cs deleted file mode 100644 index 6318efeda..000000000 --- a/BTCPayServer.Tests/PlayerwightExtensions.cs +++ /dev/null @@ -1,153 +0,0 @@ -using System; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using BTCPayServer.Tests.Logging; -using Microsoft.AspNetCore.Mvc; -using Newtonsoft.Json; -using Newtonsoft.Json.Serialization; -using OpenQA.Selenium; -using OpenQA.Selenium.Support.UI; -using PlaywrightSharp; -using Xunit; - -namespace BTCPayServer.Tests -{ - public static class PlayerwightExtensions - { - private static readonly JsonSerializerSettings JsonSettings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }; - public static string ToJson(this object o) => JsonConvert.SerializeObject(o, Formatting.None, JsonSettings); - - public static async Task LogIn(this PlayWrightTester s, string email) - { - await s.Page.TypeAsync("#Email", email); - await s.Page.TypeAsync("#Password", "123456"); - await s.Page.ClickAsync("#LoginButton"); - await s.Page.AssertNoError(); - } - - public static async Task AssertNoError(this IPage driver) - { - try - { - Assert.NotEmpty(driver.FindElements(By.ClassName("navbar-brand"))); - if (driver.PageSource.Contains("alert-danger")) - { - foreach (var dangerAlert in driver.FindElements(By.ClassName("alert-danger"))) - Assert.False(dangerAlert.Displayed, "No alert should be displayed"); - } - } - catch - { - StringBuilder builder = new StringBuilder(); - builder.AppendLine(); - foreach (var logKind in new[] { LogType.Browser, LogType.Client, LogType.Driver, LogType.Server }) - { - try - { - var logs = driver.Manage().Logs.GetLog(logKind); - builder.AppendLine($"PlayWright [{logKind}]:"); - foreach (var entry in logs) - { - builder.AppendLine($"[{entry.Level}]: {entry.Message}"); - } - } - catch - { - // ignored - } - - builder.AppendLine("---------"); - } - Logs.Tester.LogInformation(builder.ToString()); - builder = new StringBuilder(); - builder.AppendLine("PlayWright [Sources]:"); - builder.AppendLine(await driver.GetContentAsync()); - builder.AppendLine("---------"); - Logs.Tester.LogInformation(builder.ToString()); - throw; - } - } - public static T AssertViewModel(this IActionResult result) - { - Assert.NotNull(result); - var vr = Assert.IsType(result); - return Assert.IsType(vr.Model); - } - public static async Task AssertViewModelAsync(this Task task) - { - var result = await task; - Assert.NotNull(result); - var vr = Assert.IsType(result); - return Assert.IsType(vr.Model); - } - - public static void AssertElementNotFound(this IPage driver, By by) - { - DateTimeOffset now = DateTimeOffset.Now; - var wait = PlayWrightTester.ImplicitWait; - - while (DateTimeOffset.UtcNow - now < wait) - { - try - { - var webElement = driver.FindElement(by); - if (!webElement.Displayed) - return; - } - catch (NoSuchWindowException) - { - return; - } - catch (NoSuchElementException) - { - return; - } - Thread.Sleep(50); - } - Assert.False(true, "Elements was found"); - } - - public static void UntilJsIsReady(this WebDriverWait wait) - { - wait.Until(d=>((IJavaScriptExecutor)d).ExecuteScript("return document.readyState").Equals("complete")); - wait.Until(d=>((IJavaScriptExecutor)d).ExecuteScript("return typeof(jQuery) === 'undefined' || jQuery.active === 0").Equals(true)); - } - - public static IWebElement WaitForElement(this IPage driver, By selector) - { - var wait = new WebDriverWait(driver, PlayWrightTester.ImplicitWait); - wait.UntilJsIsReady(); - - var el = driver.FindElement(selector); - wait.Until(d => el.Displayed); - - return el; - } - - public static void WaitForAndClick(this IPage driver, By selector) - { - var wait = new WebDriverWait(driver, PlayWrightTester.ImplicitWait); - wait.UntilJsIsReady(); - - var el = driver.FindElement(selector); - wait.Until(d => el.Displayed && el.Enabled); - el.Click(); - - wait.UntilJsIsReady(); - } - - public static async Task SetCheckbox(this IPage driver, string selector, bool value) - { - var element = await driver.QuerySelectorAsync(selector); - if (value) - { - await element.CheckAsync(); - } - else - { - await element.UncheckAsync(); - } - } - } -}