Merge task branch for: MCP: add missing external tools + fix status enum, branchDeleted, merge-from-review
This commit is contained in:
@@ -515,7 +515,7 @@ public sealed class ExternalMcpServiceTests : IDisposable
|
||||
var sut = BuildSut(CreateQueue());
|
||||
|
||||
var ex = await Assert.ThrowsAsync<InvalidOperationException>(
|
||||
() => sut.MergeTask(task.Id, "main", true, false, CancellationToken.None));
|
||||
() => sut.MergeTask(task.Id, "main", true, false, false, CancellationToken.None));
|
||||
Assert.Contains("Done", ex.Message);
|
||||
}
|
||||
|
||||
@@ -527,7 +527,7 @@ public sealed class ExternalMcpServiceTests : IDisposable
|
||||
var (task, _, _) = await SeedWorktreeAsync(TaskStatus.Done);
|
||||
var sut = BuildSut(CreateQueue());
|
||||
|
||||
var result = await sut.MergeTask(task.Id, "main", true, dryRun: true, CancellationToken.None);
|
||||
var result = await sut.MergeTask(task.Id, "main", true, dryRun: true, cancellationToken: CancellationToken.None);
|
||||
|
||||
Assert.False(result.Merged);
|
||||
Assert.Null(result.MergeCommit);
|
||||
@@ -595,4 +595,129 @@ public sealed class ExternalMcpServiceTests : IDisposable
|
||||
Assert.True(result.Removed);
|
||||
Assert.False(Directory.Exists(wt.WorktreePath));
|
||||
}
|
||||
|
||||
// ── GetTaskConfig ─────────────────────────────────────────────────────────
|
||||
|
||||
private ConfigMcpTools BuildConfigSut() => new(_lists, _tasks, _broadcaster);
|
||||
|
||||
[Fact]
|
||||
public async Task GetTaskConfig_NotFound_Throws()
|
||||
{
|
||||
var sut = BuildConfigSut();
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(
|
||||
() => sut.GetTaskConfig("does-not-exist", CancellationToken.None));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetTaskConfig_NoOverrides_ReturnsNull()
|
||||
{
|
||||
var listId = await SeedListAsync();
|
||||
var task = await SeedTaskAsync(listId);
|
||||
var sut = BuildConfigSut();
|
||||
|
||||
var result = await sut.GetTaskConfig(task.Id, CancellationToken.None);
|
||||
|
||||
Assert.Null(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetTaskConfig_WithOverrides_ReturnsValues()
|
||||
{
|
||||
var listId = await SeedListAsync();
|
||||
var task = await SeedTaskAsync(listId);
|
||||
await _tasks.UpdateAgentSettingsAsync(task.Id, "claude-sonnet-4-6", "be concise", null, 10, CancellationToken.None);
|
||||
var sut = BuildConfigSut();
|
||||
|
||||
var result = await sut.GetTaskConfig(task.Id, CancellationToken.None);
|
||||
|
||||
Assert.NotNull(result);
|
||||
Assert.Equal("claude-sonnet-4-6", result.Model);
|
||||
Assert.Equal("be concise", result.SystemPrompt);
|
||||
Assert.Null(result.AgentPath);
|
||||
Assert.Equal(10, result.MaxTurns);
|
||||
}
|
||||
|
||||
// ── GetTaskStatusValues ───────────────────────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public async Task GetTaskStatusValues_ContainsAllStatuses()
|
||||
{
|
||||
var sut = NewService();
|
||||
var values = await sut.GetTaskStatusValues();
|
||||
var names = values.Select(v => v.Status).ToHashSet();
|
||||
|
||||
foreach (var status in Enum.GetValues<TaskStatus>())
|
||||
Assert.Contains(status.ToString(), names);
|
||||
}
|
||||
|
||||
// ── ListTasks status filter ───────────────────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public async Task ListTasks_FilterByWaitingForReview_ReturnsMatchingTasks()
|
||||
{
|
||||
var listId = await SeedListAsync();
|
||||
await SeedTaskAsync(listId, "wfr", TaskStatus.WaitingForReview);
|
||||
await SeedTaskAsync(listId, "idle", TaskStatus.Idle);
|
||||
var sut = NewService();
|
||||
|
||||
var result = await sut.ListTasks(listId, null, "WaitingForReview", CancellationToken.None);
|
||||
|
||||
Assert.Single(result);
|
||||
Assert.Equal("WaitingForReview", result[0].Status);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ListTasks_FilterByWaitingForChildren_ReturnsMatchingTasks()
|
||||
{
|
||||
var listId = await SeedListAsync();
|
||||
await SeedTaskAsync(listId, "wfc", TaskStatus.WaitingForChildren);
|
||||
await SeedTaskAsync(listId, "done", TaskStatus.Done);
|
||||
var sut = NewService();
|
||||
|
||||
var result = await sut.ListTasks(listId, null, "WaitingForChildren", CancellationToken.None);
|
||||
|
||||
Assert.Single(result);
|
||||
Assert.Equal("WaitingForChildren", result[0].Status);
|
||||
}
|
||||
|
||||
// ── MergeTask allowWaitingForReview ───────────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public async Task MergeTask_WaitingForReview_WithoutFlag_Throws()
|
||||
{
|
||||
var listId = await SeedListAsync();
|
||||
var task = await SeedTaskAsync(listId, status: TaskStatus.WaitingForReview);
|
||||
var sut = BuildSut(CreateQueue());
|
||||
|
||||
var ex = await Assert.ThrowsAsync<InvalidOperationException>(
|
||||
() => sut.MergeTask(task.Id, "main", true, false, false, CancellationToken.None));
|
||||
Assert.Contains("Done", ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MergeTask_WaitingForReview_WithFlag_DryRun_Succeeds()
|
||||
{
|
||||
if (!GitAvailable) { Assert.True(true, "git not available -- skipping"); return; }
|
||||
|
||||
var (task, _, _) = await SeedWorktreeAsync(TaskStatus.WaitingForReview);
|
||||
var sut = BuildSut(CreateQueue());
|
||||
|
||||
var result = await sut.MergeTask(task.Id, "main", true, dryRun: true, allowWaitingForReview: true, CancellationToken.None);
|
||||
|
||||
Assert.False(result.Merged);
|
||||
Assert.Null(result.MergeCommit);
|
||||
}
|
||||
|
||||
// ── ContinueTask validation ───────────────────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public async Task ContinueTask_EmptyPrompt_Throws()
|
||||
{
|
||||
var listId = await SeedListAsync();
|
||||
var task = await SeedTaskAsync(listId);
|
||||
var sut = NewService();
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(
|
||||
() => sut.ContinueTask(task.Id, " ", CancellationToken.None));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user