Files
AX-Copilot-Codex/src/AxCopilot.Tests/Services/DraftQueueProcessorServiceTests.cs

87 lines
3.5 KiB
C#

using AxCopilot.Services;
using FluentAssertions;
using Xunit;
namespace AxCopilot.Tests.Services;
public class DraftQueueProcessorServiceTests
{
[Fact]
public void TryStartNext_PicksPreferredDraftAndMarksItRunning()
{
var session = new ChatSessionStateService();
var processor = new DraftQueueProcessorService();
var first = session.EnqueueDraft("Chat", "first", "next");
var second = session.EnqueueDraft("Chat", "second", "later");
var started = processor.TryStartNext(session, "Chat", preferredDraftId: second!.Id);
started.Should().NotBeNull();
started!.Id.Should().Be(second.Id);
session.GetDraftQueueItems("Chat").Single(x => x.Id == second.Id).State.Should().Be("running");
session.GetDraftQueueItems("Chat").Single(x => x.Id == first!.Id).State.Should().Be("queued");
}
[Fact]
public void HandleFailure_SchedulesRetryBeforeRetryLimit()
{
var session = new ChatSessionStateService();
var processor = new DraftQueueProcessorService();
var item = session.EnqueueDraft("Chat", "retry me", "next");
processor.TryStartNext(session, "Chat", preferredDraftId: item!.Id);
var handled = processor.HandleFailure(session, "Chat", item.Id, "boom", cancelled: false, maxAutoRetries: 3);
handled.Should().BeTrue();
var stored = session.GetDraftQueueItems("Chat").Single(x => x.Id == item.Id);
stored.State.Should().Be("queued");
stored.NextRetryAt.Should().NotBeNull();
}
[Fact]
public void PromoteReadyBlockedItems_ClearsExpiredRetryWindow()
{
var session = new ChatSessionStateService();
var processor = new DraftQueueProcessorService();
var item = session.EnqueueDraft("Chat", "retry me", "next");
processor.TryStartNext(session, "Chat", preferredDraftId: item!.Id);
processor.HandleFailure(session, "Chat", item.Id, "boom", cancelled: false, maxAutoRetries: 3);
session.CurrentConversation!.DraftQueueItems[0].NextRetryAt = DateTime.Now.AddSeconds(-1);
var promoted = processor.PromoteReadyBlockedItems(session, "Chat");
promoted.Should().Be(1);
session.CurrentConversation!.DraftQueueItems[0].NextRetryAt.Should().BeNull();
}
[Fact]
public void ClearCompleted_RemovesCompletedItems()
{
var session = new ChatSessionStateService();
var processor = new DraftQueueProcessorService();
var item = session.EnqueueDraft("Chat", "done item", "next");
processor.TryStartNext(session, "Chat", preferredDraftId: item!.Id);
processor.Complete(session, "Chat", item.Id);
var removed = processor.ClearCompleted(session, "Chat");
removed.Should().Be(1);
session.GetDraftQueueItems("Chat").Should().BeEmpty();
}
[Fact]
public void TryStartNext_AndHandleFailure_RecordQueueTasks()
{
var session = new ChatSessionStateService();
var processor = new DraftQueueProcessorService();
var taskRuns = new TaskRunService();
var item = session.EnqueueDraft("Chat", "retry me", "next");
processor.TryStartNext(session, "Chat", preferredDraftId: item!.Id, taskRuns: taskRuns);
processor.HandleFailure(session, "Chat", item.Id, "boom", cancelled: false, maxAutoRetries: 3, taskRuns: taskRuns);
taskRuns.ActiveTasks.Should().BeEmpty();
taskRuns.RecentTasks.Should().ContainSingle(t => t.Kind == "queue" && t.Status == "blocked");
}
}