fix(board): commit a search only after its query succeeds and report read failures
A failed read on a UI path (sort change, clear, refresh after a write, opening a card, the tag picker, the tags tab) used to escape as an unhandled exception. Reads now run before the view is cleared and report Error_Read_* instead; the active filter changes only once its query has run. DataWritten and TagsChanged fire only after a successful refresh, so a broken database shows one dialog.
This commit is contained in:
1 parent
23f7806e2d
commit
f9f0e71453
9 files changed
+216
-33
No files matched your search
@@ -285,6 +285,52 @@ public class BoardViewModelTests
|
||||
Assert.AreEqual(0, fixture.Repository.GetCards().Count);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task FailedSearchQueryIsReportedAndKeepsThePreviousResultAndFilter()
|
||||
{
|
||||
using var fixture = new Fixture();
|
||||
ColumnModel column = fixture.Repository.AddColumn("A", "");
|
||||
fixture.Repository.AddCard(column.Id, "alpha", "", []);
|
||||
fixture.Repository.AddCard(column.Id, "beta", "", []);
|
||||
BoardViewModel board = fixture.CreateBoard();
|
||||
board.SearchText = "alpha";
|
||||
await board.SearchCommand.ExecuteAsync(null);
|
||||
CompiledSearch? alphaFilter = board.ActiveFilter;
|
||||
|
||||
// Every read fails from now on.
|
||||
fixture.Repository.Dispose();
|
||||
board.SearchText = "beta";
|
||||
await board.SearchCommand.ExecuteAsync(null);
|
||||
|
||||
var error = (MessageDialogViewModel)fixture.Dialogs.Shown.Single();
|
||||
Assert.AreEqual(Resources.Error_Read_Title, error.Title);
|
||||
Assert.AreSame(alphaFilter, board.ActiveFilter);
|
||||
CollectionAssert.AreEqual(new[] { "alpha" }, board.Columns.Single().Cards.Select(card => card.Title).ToArray());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ReadFailuresOnBoardCommandsAreReportedInsteadOfThrown()
|
||||
{
|
||||
using var fixture = new Fixture();
|
||||
ColumnModel column = fixture.Repository.AddColumn("A", "");
|
||||
CardModel card = fixture.Repository.AddCard(column.Id, "a", "", []);
|
||||
BoardViewModel board = fixture.CreateBoard();
|
||||
var editor = CardEditorDialogViewModel.ForExistingCard(fixture.Repository, fixture.Dialogs, card, confirmDiscard: false);
|
||||
fixture.Repository.Dispose();
|
||||
|
||||
board.SelectedSort = board.SortOptions.Single(option => (CardSortOption)option.Value == CardSortOption.Title);
|
||||
await board.ClearSearchCommand.ExecuteAsync(null);
|
||||
await board.Columns.Single().Cards.Single().EditCommand.ExecuteAsync(null);
|
||||
await board.Columns.Single().Cards.Single().MoveToCommand.ExecuteAsync(column.Id);
|
||||
await editor.AddTagCommand.ExecuteAsync(null);
|
||||
|
||||
// Sort, clear, edit, the failed move with its refresh, and the tag picker.
|
||||
string read = Resources.Error_Read_Title;
|
||||
CollectionAssert.AreEqual(
|
||||
new[] { read, read, read, Resources.Error_Operation_Title, read, read },
|
||||
fixture.Dialogs.Shown.Select(dialog => ((MessageDialogViewModel)dialog).Title).ToArray());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TagPickerReportsInvalidColorAndDuplicateNameWithoutClosing()
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user