Improve create first store view (#5181)

* Improve create first store view

Closes #5008.

* Fix tests
This commit is contained in:
d11n
2023-07-19 15:21:16 +02:00
committed by GitHub
parent 19d5e64063
commit 0017f236a7
6 changed files with 85 additions and 43 deletions

View File

@@ -23,7 +23,7 @@
<PackageReference Include="Newtonsoft.Json.Schema" Version="3.0.14" /> <PackageReference Include="Newtonsoft.Json.Schema" Version="3.0.14" />
<PackageReference Include="Selenium.Support" Version="4.1.1" /> <PackageReference Include="Selenium.Support" Version="4.1.1" />
<PackageReference Include="Selenium.WebDriver" Version="4.1.1" /> <PackageReference Include="Selenium.WebDriver" Version="4.1.1" />
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="112.0.5615.4900" /> <PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="114.0.5735.9000" />
<PackageReference Include="xunit" Version="2.4.2" /> <PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>

View File

@@ -393,6 +393,10 @@ namespace BTCPayServer.Tests
public void GoToHome() public void GoToHome()
{ {
Driver.Navigate().GoToUrl(ServerUri); Driver.Navigate().GoToUrl(ServerUri);
if (Driver.PageSource.Contains("id=\"SkipWizard\""))
{
Driver.FindElement(By.Id("SkipWizard")).Click();
}
} }
public void Logout() public void Logout()

View File

@@ -57,10 +57,11 @@ namespace BTCPayServer.Tests
using var s = CreateSeleniumTester(); using var s = CreateSeleniumTester();
await s.StartAsync(); await s.StartAsync();
s.RegisterNewUser(true); s.RegisterNewUser(true);
s.Driver.FindElement(By.Id("Nav-ServerSettings")).Click(); s.GoToHome();
s.GoToServer();
s.Driver.AssertNoError(); s.Driver.AssertNoError();
s.ClickOnAllSectionLinks(); s.ClickOnAllSectionLinks();
s.Driver.FindElement(By.Id("Nav-ServerSettings")).Click(); s.GoToServer();
s.Driver.FindElement(By.LinkText("Services")).Click(); s.Driver.FindElement(By.LinkText("Services")).Click();
TestLogs.LogInformation("Let's check if we can access the logs"); TestLogs.LogInformation("Let's check if we can access the logs");
@@ -247,7 +248,8 @@ namespace BTCPayServer.Tests
s.Server.ActivateLightning(); s.Server.ActivateLightning();
await s.StartAsync(); await s.StartAsync();
s.RegisterNewUser(true); s.RegisterNewUser(true);
s.Driver.FindElement(By.Id("Nav-ServerSettings")).Click(); s.GoToHome();
s.GoToServer();
s.Driver.AssertNoError(); s.Driver.AssertNoError();
s.Driver.FindElement(By.LinkText("Services")).Click(); s.Driver.FindElement(By.LinkText("Services")).Click();
@@ -314,6 +316,7 @@ namespace BTCPayServer.Tests
await s.StartAsync(); await s.StartAsync();
//Register & Log Out //Register & Log Out
var email = s.RegisterNewUser(); var email = s.RegisterNewUser();
s.GoToHome();
s.Logout(); s.Logout();
s.Driver.AssertNoError(); s.Driver.AssertNoError();
Assert.Contains("/login", s.Driver.Url); Assert.Contains("/login", s.Driver.Url);
@@ -349,6 +352,7 @@ namespace BTCPayServer.Tests
s.Driver.FindElement(By.Id("Password")).SendKeys("abc???"); s.Driver.FindElement(By.Id("Password")).SendKeys("abc???");
s.Driver.FindElement(By.Id("LoginButton")).Click(); s.Driver.FindElement(By.Id("LoginButton")).Click();
s.GoToHome();
s.GoToProfile(); s.GoToProfile();
s.ClickOnAllSectionLinks(); s.ClickOnAllSectionLinks();
@@ -356,6 +360,7 @@ namespace BTCPayServer.Tests
s.Logout(); s.Logout();
s.GoToRegister(); s.GoToRegister();
s.RegisterNewUser(true); s.RegisterNewUser(true);
s.GoToHome();
s.GoToServer(ServerNavPages.Users); s.GoToServer(ServerNavPages.Users);
s.Driver.FindElement(By.Id("CreateUser")).Click(); s.Driver.FindElement(By.Id("CreateUser")).Click();
@@ -378,6 +383,7 @@ namespace BTCPayServer.Tests
s.Driver.FindElement(By.Id("LoginButton")).Click(); s.Driver.FindElement(By.Id("LoginButton")).Click();
// We should be logged in now // We should be logged in now
s.GoToHome();
s.Driver.FindElement(By.Id("mainNav")); s.Driver.FindElement(By.Id("mainNav"));
//let's test delete user quickly while we're at it //let's test delete user quickly while we're at it
@@ -642,7 +648,7 @@ namespace BTCPayServer.Tests
// verify redirected to create store page // verify redirected to create store page
Assert.EndsWith("/stores/create", s.Driver.Url); Assert.EndsWith("/stores/create", s.Driver.Url);
Assert.Contains("Create your first store", s.Driver.PageSource); Assert.Contains("Create your first store", s.Driver.PageSource);
Assert.Contains("To start accepting payments, set up a store.", s.Driver.PageSource); Assert.Contains("Create a store to begin accepting payments", s.Driver.PageSource);
Assert.False(s.Driver.PageSource.Contains("id=\"StoreSelectorDropdown\""), "Store selector dropdown should not be present"); Assert.False(s.Driver.PageSource.Contains("id=\"StoreSelectorDropdown\""), "Store selector dropdown should not be present");
(_, string storeId) = s.CreateNewStore(); (_, string storeId) = s.CreateNewStore();
@@ -2583,6 +2589,7 @@ namespace BTCPayServer.Tests
using var s = CreateSeleniumTester(); using var s = CreateSeleniumTester();
await s.StartAsync(); await s.StartAsync();
var user = s.RegisterNewUser(); var user = s.RegisterNewUser();
s.GoToHome();
s.GoToProfile(ManageNavPages.LoginCodes); s.GoToProfile(ManageNavPages.LoginCodes);
var code = s.Driver.FindElement(By.Id("logincode")).GetAttribute("value"); var code = s.Driver.FindElement(By.Id("logincode")).GetAttribute("value");
s.Driver.FindElement(By.Id("regeneratecode")).Click(); s.Driver.FindElement(By.Id("regeneratecode")).Click();
@@ -2594,14 +2601,12 @@ namespace BTCPayServer.Tests
s.Driver.SetAttribute("LoginCode", "value", "bad code"); s.Driver.SetAttribute("LoginCode", "value", "bad code");
s.Driver.InvokeJSFunction("logincode-form", "submit"); s.Driver.InvokeJSFunction("logincode-form", "submit");
s.Driver.SetAttribute("LoginCode", "value", code); s.Driver.SetAttribute("LoginCode", "value", code);
s.Driver.InvokeJSFunction("logincode-form", "submit"); s.Driver.InvokeJSFunction("logincode-form", "submit");
s.GoToProfile(); s.GoToHome();
Assert.Contains(user, s.Driver.PageSource); Assert.Contains(user, s.Driver.PageSource);
} }
// For god know why, selenium have problems clicking on the save button, resulting in ultimate hacks // For god know why, selenium have problems clicking on the save button, resulting in ultimate hacks
// to make it works. // to make it works.
private void SudoForceSaveLightningSettingsRightNowAndFast(SeleniumTester s, string cryptoCode) private void SudoForceSaveLightningSettingsRightNowAndFast(SeleniumTester s, string cryptoCode)
@@ -2620,7 +2625,6 @@ retry:
} }
} }
[Fact] [Fact]
[Trait("Selenium", "Selenium")] [Trait("Selenium", "Selenium")]
public async Task CanUseLNURLAuth() public async Task CanUseLNURLAuth()
@@ -2628,6 +2632,7 @@ retry:
using var s = CreateSeleniumTester(); using var s = CreateSeleniumTester();
await s.StartAsync(); await s.StartAsync();
var user = s.RegisterNewUser(true); var user = s.RegisterNewUser(true);
s.GoToHome();
s.GoToProfile(ManageNavPages.TwoFactorAuthentication); s.GoToProfile(ManageNavPages.TwoFactorAuthentication);
s.Driver.FindElement(By.Name("Name")).SendKeys("ln wallet"); s.Driver.FindElement(By.Name("Name")).SendKeys("ln wallet");
s.Driver.FindElement(By.Name("type")) s.Driver.FindElement(By.Name("type"))
@@ -2676,7 +2681,8 @@ retry:
{ {
using var s = CreateSeleniumTester(newDb: true); using var s = CreateSeleniumTester(newDb: true);
await s.StartAsync(); await s.StartAsync();
var user = s.RegisterNewUser(true); s.RegisterNewUser(true);
s.GoToHome();
s.GoToServer(ServerNavPages.Roles); s.GoToServer(ServerNavPages.Roles);
var existingServerRoles = s.Driver.FindElement(By.CssSelector("table")).FindElements(By.CssSelector("tr")); var existingServerRoles = s.Driver.FindElement(By.CssSelector("table")).FindElements(By.CssSelector("tr"));
Assert.Equal(3, existingServerRoles.Count); Assert.Equal(3, existingServerRoles.Count);

View File

@@ -39,12 +39,12 @@ namespace BTCPayServer.Controllers
[HttpGet("create")] [HttpGet("create")]
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie, Policy = Policies.CanModifyStoreSettingsUnscoped)] [Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie, Policy = Policies.CanModifyStoreSettingsUnscoped)]
public async Task<IActionResult> CreateStore() public async Task<IActionResult> CreateStore(bool skipWizard)
{ {
var stores = await _repo.GetStoresByUserId(GetUserId()); var stores = await _repo.GetStoresByUserId(GetUserId());
var vm = new CreateStoreViewModel var vm = new CreateStoreViewModel
{ {
IsFirstStore = !stores.Any(), IsFirstStore = !(stores.Any() || skipWizard),
DefaultCurrency = StoreBlob.StandardDefaultCurrency, DefaultCurrency = StoreBlob.StandardDefaultCurrency,
Exchanges = GetExchangesSelectList(null) Exchanges = GetExchangesSelectList(null)
}; };

View File

@@ -1,5 +1,6 @@
@model BTCPayServer.Models.StoreViewModels.CreateStoreViewModel @model BTCPayServer.Models.StoreViewModels.CreateStoreViewModel
@{ @{
Layout = Model.IsFirstStore ? "_LayoutWizard" : "_Layout";
ViewData.SetActivePage(StoreNavPages.Create, Model.IsFirstStore ? "Create your first store" : "Create a new store"); ViewData.SetActivePage(StoreNavPages.Create, Model.IsFirstStore ? "Create your first store" : "Create a new store");
} }
@@ -18,41 +19,48 @@
</script> </script>
} }
<partial name="_StatusMessage" />
@if (Model.IsFirstStore) @if (Model.IsFirstStore)
{ {
<h2>@ViewData["Title"]</h2> @section Navbar {
<p class="lead text-secondary">To start accepting payments, set up a store.</p> <a asp-route-skipWizard="true" class="cancel" id="SkipWizard">
<vc:icon symbol="close" />
</a>
}
@section PageHeadContent {
<style>
#FirstStore { max-width: 27rem; margin: 0 auto; text-align: center; }
#FirstStore .main-logo { height: 4rem; width: 18rem; }
#FirstStore .main-logo.main-logo-btcpay { height: 4.5rem; width: 2.5rem; }
#FirstStore .main-logo-btcpay .main-logo-btcpay--large { display: none; }
#FirstStore .form-control, #FirstStore .form-select { width: 100%; }
#FirstStore .form-text { font-size: var(--btcpay-font-size-s); }
#FirstStore .form-group:last-of-type { text-align: center; }
</style>
}
<div id="FirstStore">
<a asp-controller="UIHome" asp-action="Index" tabindex="-1" class="d-inline-block mb-4">
<vc:main-logo />
</a>
<h1 class="h2 mb-3">@ViewData["Title"]</h1>
<p class="lead text-secondary">Create a store to begin accepting payments.</p>
<div class="text-start">
<partial name="_StatusMessage"/>
<partial name="_CreateStoreForm" model="Model" />
</div>
</div>
} }
else else
{ {
<h2 class="mt-1 mb-4">@ViewData["Title"]</h2> <h2 class="mt-1 mb-4">@ViewData["Title"]</h2>
} <div class="row">
<div class="row"> <div class="col-xl-8 col-xxl-constrain">
<div class="col-xl-8 col-xxl-constrain"> <partial name="_CreateStoreForm" model="Model" />
<form asp-action="CreateStore"> </div>
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="form-label" data-required></label>
<input asp-for="Name" class="form-control w-300px" required />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="DefaultCurrency" class="form-label" data-required></label>
<input asp-for="DefaultCurrency" class="form-control w-300px" currency-selection />
<span asp-validation-for="DefaultCurrency" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="PreferredExchange" class="form-label" data-required></label>
<select asp-for="PreferredExchange" asp-items="Model.Exchanges" class="form-select w-300px"></select>
<div class="form-text mt-2 only-for-js">The recommended price source gets chosen based on the default currency.</div>
<span asp-validation-for="PreferredExchange" class="text-danger"></span>
</div>
<div class="form-group mt-4">
<input type="submit" value="Create" class="btn btn-primary" id="Create" />
</div>
</form>
</div> </div>
</div> }

View File

@@ -0,0 +1,24 @@
@model BTCPayServer.Models.StoreViewModels.CreateStoreViewModel
<form asp-action="CreateStore">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="form-label" data-required></label>
<input asp-for="Name" class="form-control w-300px" required />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="DefaultCurrency" class="form-label" data-required></label>
<input asp-for="DefaultCurrency" class="form-control w-300px" currency-selection />
<span asp-validation-for="DefaultCurrency" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="PreferredExchange" class="form-label" data-required></label>
<select asp-for="PreferredExchange" asp-items="Model.Exchanges" class="form-select w-300px"></select>
<div class="form-text mt-2 only-for-js">The recommended price source gets chosen based on the default currency.</div>
<span asp-validation-for="PreferredExchange" class="text-danger"></span>
</div>
<div class="form-group mt-4">
<input type="submit" value="Create Store" class="btn btn-primary" id="Create" />
</div>
</form>