Merge pull request #6675 from wbalbo/fix-add-confirmation-deletion-email-rules

Fix: adding a confirmation for the deletion of Email Rule
This commit is contained in:
Nicolas Dorier
2025-04-21 00:02:24 +09:00
committed by GitHub
4 changed files with 48 additions and 23 deletions

View File

@@ -138,26 +138,37 @@ retry:
}
public IWebElement FindAlertMessage(params StatusMessageModel.StatusSeverity[] severity)
{
var className = string.Join(", ", severity.Select(statusSeverity => $".alert-{StatusMessageModel.ToString(statusSeverity)}"));
IWebElement el;
int retry = 0;
retry:
try
{
var elements = Driver.FindElements(By.CssSelector(className));
el = elements.FirstOrDefault(e => e.Displayed);
if (el is null)
el = elements.FirstOrDefault();
if (el is null)
var className = string.Join(", ", severity.Select(statusSeverity => $".alert-{StatusMessageModel.ToString(statusSeverity)}"));
IWebElement el;
try
{
var elements = Driver.FindElements(By.CssSelector(className));
el = elements.FirstOrDefault(e => e.Displayed);
if (el is null)
el = elements.FirstOrDefault();
if (el is null)
el = Driver.WaitForElement(By.CssSelector(className));
}
catch (NoSuchElementException)
{
el = Driver.WaitForElement(By.CssSelector(className));
}
if (el is null)
throw new NoSuchElementException($"Unable to find {className}");
if (!el.Displayed)
throw new ElementNotVisibleException($"{className} is present, but not displayed: {el.GetAttribute("id")} - Text: {el.Text}");
return el;
}
catch (NoSuchElementException)
// Selenium sometimes sucks...
catch (StaleElementReferenceException) when (retry < 5)
{
el = Driver.WaitForElement(By.CssSelector(className));
retry++;
goto retry;
}
if (el is null)
throw new NoSuchElementException($"Unable to find {className}");
if (!el.Displayed)
throw new ElementNotVisibleException($"{className} is present, but not displayed: {el.GetAttribute("id")} - Text: {el.Text}");
return el;
}
public string Link(string relativeLink)

View File

@@ -866,6 +866,7 @@ namespace BTCPayServer.Tests
s.Driver.FindElement(By.Id("SaveEmailRules")).Click();
// Ensure that the rule is created
s.FindAlertMessage();
Assert.DoesNotContain("There are no rules yet.", s.Driver.PageSource);
Assert.Contains("invoicecreated@gmail.com", s.Driver.PageSource);
Assert.Contains("Invoice {Invoice.Id} created", s.Driver.PageSource);
@@ -881,6 +882,7 @@ namespace BTCPayServer.Tests
s.Driver.FindElement(By.Id("SaveEmailRules")).Click();
// Validate the second rule is added
s.FindAlertMessage();
Assert.Contains("statuschanged@gmail.com", s.Driver.PageSource);
Assert.Contains("Status changed!", s.Driver.PageSource);
@@ -897,20 +899,27 @@ namespace BTCPayServer.Tests
s.Driver.FindElement(By.Id("SaveEmailRules")).Click();
// Validate that the email is updated in the list of email rules
s.FindAlertMessage();
Assert.Contains("changedagain@gmail.com", s.Driver.PageSource);
Assert.DoesNotContain("statuschanged@gmail.com", s.Driver.PageSource);
// Delete both email rules
var deleteLinks = s.Driver.FindElements(By.XPath("//a[contains(text(), 'Delete')]"));
var deleteLinks = s.Driver.FindElements(By.XPath("//a[contains(text(), 'Remove')]"));
Assert.True(deleteLinks.Count == 2, "Expected exactly two delete buttons but found a different number.");
deleteLinks[0].Click();
s.Driver.WaitForElement(By.Id("ConfirmInput")).SendKeys("REMOVE");
s.Driver.FindElement(By.Id("ConfirmContinue")).Click();
deleteLinks = s.Driver.FindElements(By.XPath("//a[contains(text(), 'Delete')]")); // Refresh list
s.FindAlertMessage();
deleteLinks = s.Driver.FindElements(By.XPath("//a[contains(text(), 'Remove')]")); // Refresh list
Assert.True(deleteLinks.Count == 1, "Expected one delete button remaining.");
deleteLinks[0].Click();
s.Driver.WaitForElement(By.Id("ConfirmInput")).SendKeys("REMOVE");
s.Driver.FindElement(By.Id("ConfirmContinue")).Click();
s.FindAlertMessage();
// Validate that there are no more rules
Assert.Contains("There are no rules yet.", s.Driver.PageSource);
}

View File

@@ -72,6 +72,7 @@ namespace BTCPayServer.Controllers
store.SetStoreBlob(blob);
await _storeRepo.UpdateStore(store);
this.TempData.SetStatusSuccess(StringLocalizer["Email rule successfully created"]);
return RedirectToAction(nameof(StoreEmailRulesList), new { storeId });
}
@@ -111,6 +112,7 @@ namespace BTCPayServer.Controllers
store.SetStoreBlob(blob);
await _storeRepo.UpdateStore(store);
this.TempData.SetStatusSuccess(StringLocalizer["Email rule successfully updated"]);
return RedirectToAction(nameof(StoreEmailRulesList), new { storeId });
}
@@ -128,6 +130,7 @@ namespace BTCPayServer.Controllers
store.SetStoreBlob(blob);
await _storeRepo.UpdateStore(store);
this.TempData.SetStatusSuccess(StringLocalizer["Email rule successfully deleted"]);
return RedirectToAction(nameof(StoreEmailRulesList), new { storeId });
}

View File

@@ -1,3 +1,4 @@
@using BTCPayServer.Abstractions.Models
@using BTCPayServer.Client
@using BTCPayServer.TagHelpers
@using Microsoft.AspNetCore.Mvc.TagHelpers
@@ -38,7 +39,7 @@
<th>Customer Email</th>
<th>To</th>
<th>Subject</th>
<th>Actions</th>
<th class="actions-col" permission="@Policies.CanModifyStoreSettings"></th>
</tr>
</thead>
<tbody>
@@ -49,12 +50,11 @@
<td>@(rule.value.CustomerEmail ? "Yes" : "No")</td>
<td>@rule.value.To</td>
<td>@rule.value.Subject</td>
<td>
<a asp-action="StoreEmailRulesEdit" asp-route-storeId="@storeId" asp-route-ruleIndex="@rule.index">Edit</a>
-
<form asp-action="StoreEmailRulesDelete" asp-route-storeId="@storeId" asp-route-ruleIndex="@rule.index" method="post" style="display:inline;">
<a href="#" class="text-danger" onclick="event.preventDefault(); this.closest('form').submit();">Delete</a>
</form>
<td class="actions-col" permission="@Policies.CanModifyStoreSettings">
<div class="d-inline-flex align-items-center gap-3">
<a asp-action="StoreEmailRulesEdit" asp-route-storeId="@storeId" asp-route-ruleIndex="@rule.index">Edit</a>
<a asp-action="StoreEmailRulesDelete" asp-route-storeId="@storeId" asp-route-ruleIndex="@rule.index" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="@ViewLocalizer["This action will remove the rule with the trigger <b>{0}</b>.", Html.Encode(rule.value.Trigger)]" data-confirm-input="@StringLocalizer["REMOVE"]" text-translate="true">Remove</a>
</div>
</td>
</tr>
}
@@ -68,3 +68,5 @@ else
There are no rules yet.
</p>
}
<partial name="_Confirm" model="@(new ConfirmModel(StringLocalizer["Remove email rule"], StringLocalizer["This action will remove this rule. Are you sure?"], StringLocalizer["Delete"]))" permission="@Policies.CanModifyStoreSettings" />