fix(ui): Dequeue-X auf blockierten Queue-Zeilen anzeigen und Kette konsistent halten

CanRemoveFromQueue schloss IsWaiting (queued+blocked) faelschlich aus, sodass ein
Kettenglied in der Mitte nicht entfernbar war. Zusaetzlich unblockt
TaskStateService.DequeueToIdleAsync jetzt den Nachfolger eines dequeueten
Kettenglieds, sonst bliebe er dauerhaft auf einen nicht mehr laufenden
Vorgaenger blockiert.
This commit is contained in:
mika kuns
2026-09-02 22:34:50 +02:00
parent 77c70d74cb
commit df3e7ba0c7
6 changed files with 48 additions and 2 deletions
@@ -41,6 +41,23 @@ public class TaskRowContextMenuTests
Assert.NotNull(row.SendToQueueDisabledReason);
}
[Fact]
public void CanRemoveFromQueue_True_When_Queued_And_Blocked()
{
var row = MakeRow();
row.Status = TaskStatus.Queued;
row.BlockedByTaskId = "predecessor-id";
Assert.True(row.CanRemoveFromQueue);
}
[Fact]
public void CanRemoveFromQueue_False_When_Idle()
{
var row = MakeRow();
row.Status = TaskStatus.Idle;
Assert.False(row.CanRemoveFromQueue);
}
[Fact]
public void CancelDisabledReason_Null_While_Running()
{
@@ -585,6 +585,23 @@ public sealed class TaskStateServiceTests : IDisposable
Assert.Equal(TaskStatus.Running, await GetStatusAsync(id));
}
[Fact]
public async Task DequeueToIdleAsync_MidChain_UnblocksSuccessor()
{
// pred (queued, blocked) is removed from the queue in the middle of a chain;
// successor was blocked on pred and must not be left wedged forever.
var pred = await SeedTaskAsync(TaskStatus.Queued);
var id = await SeedTaskAsync(TaskStatus.Queued, blockedBy: pred);
var successor = await SeedTaskAsync(TaskStatus.Queued, blockedBy: id);
var result = await _sut.DequeueToIdleAsync(id, default);
Assert.True(result.Ok);
var successorTask = await GetTaskAsync(successor);
Assert.Equal(TaskStatus.Queued, successorTask.Status);
Assert.Null(successorTask.BlockedByTaskId);
}
// ─── StartPlanningAsync ───────────────────────────────────────────────
[Fact]
@@ -281,6 +281,7 @@ public class TaskRowViewModelNotificationsTests
nameof(TaskRowViewModel.IsQueued),
nameof(TaskRowViewModel.IsWaiting),
nameof(TaskRowViewModel.StatusChipClass),
nameof(TaskRowViewModel.CanRemoveFromQueue),
}, raised);
}