feat(usability): explain deleted bookings and linked transfer undo (U10)

This commit is contained in:
2026-11-02 19:26:23 +01:00
parent 2d36ab0b88
commit 1686f5769c
11 changed files with 146 additions and 14 deletions
@@ -0,0 +1,32 @@
using Bunit;
using Duempelkas.App.Components;
using Duempelkas.App.Services;
using Xunit;
namespace Duempelkas.Tests;
public class EntryLifecycleUiTests
{
[Fact]
public async Task DeleteTransfer_ExplainsBothAccounts_HidesRows_AndUndoRestoresBoth()
{
using var f = new LedgerUiFixture();
var entries = f.Service<IEntryService>();
await entries.CreateTransferAsync(1, 2, DateTime.Today, "Testtransfer", 20m);
var page = f.Context.Render<Routes>();
page.WaitForElement(".account-card").Click();
page.WaitForElement(".entry-action-menu");
page.Find("button.btn-outline-danger").Click();
page.WaitForAssertion(() => Assert.Contains("beiden Konten", page.Markup));
Assert.Contains("Barkasse", page.Find("dialog").TextContent);
Assert.Contains("Girokonto", page.Find("dialog").TextContent);
page.Find("dialog button.btn-danger").Click();
page.WaitForAssertion(() => Assert.Empty(page.FindAll("tbody tr")));
Assert.All(await entries.GetEntriesAsync(2, (int?)null), e => Assert.True(e.IsDeleted));
page.Find(".history-toggle input").Change(true);
Assert.Contains("zählt nicht zum Kontostand", page.Markup);
page.Find(".toast-success .btn").Click();
page.WaitForAssertion(() => Assert.Single(page.FindAll("tbody tr")));
Assert.All(await entries.GetEntriesAsync(2, (int?)null), e => Assert.False(e.IsDeleted));
}
}
+33
View File
@@ -0,0 +1,33 @@
using Bunit;
using Duempelkas.Infrastructure;
using Duempelkas.Infrastructure.Persistence;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace Duempelkas.Tests;
internal sealed class LedgerUiFixture : IDisposable
{
public BunitContext Context { get; } = new();
private readonly SqliteConnection anchor;
private readonly string folder = Path.Combine(Path.GetTempPath(), "duempelkas-ui-" + Guid.NewGuid().ToString("N"));
public LedgerUiFixture(bool accounts = true)
{
Directory.CreateDirectory(folder);
var connection = $"Data Source=ui-{Guid.NewGuid():N};Mode=Memory;Cache=Shared";
anchor = new SqliteConnection(connection);
anchor.Open();
Context.Services.AddInfrastructure(connection, folder);
Context.JSInterop.Mode = JSRuntimeMode.Loose;
using var db = Context.Services.GetRequiredService<IDbContextFactory<FinanceDbContext>>().CreateDbContext();
db.Database.EnsureCreated();
if (accounts)
{
db.Accounts.AddRange(new() { Name = "Barkasse", CarryoverBalance = 100m }, new() { Name = "Girokonto" });
db.SaveChanges();
}
}
public T Service<T>() where T : notnull => Context.Services.GetRequiredService<T>();
public void Dispose() { Context.Dispose(); anchor.Dispose(); Directory.Delete(folder, true); }
}