Merge claudedo/fc88143c0c704feab4ba6806cec49f4f
This commit is contained in:
@@ -216,6 +216,156 @@ public sealed class BatchMcpToolsTests : IDisposable
|
||||
Assert.Equal("the full description", found.TaskFull!.Description);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BatchGetTasks_DescriptionLongerThanCap_IsTruncated_WithFlagAndFullLength()
|
||||
{
|
||||
var listId = await SeedListAsync();
|
||||
var task = await SeedTaskAsync(listId);
|
||||
var full = new string('x', 50);
|
||||
task.Description = full;
|
||||
await _tasks.UpdateAsync(task);
|
||||
var sut = BuildSut();
|
||||
|
||||
var results = await sut.BatchGetTasks(
|
||||
new[] { task.Id }, includeDescription: true, descriptionMaxChars: 10, cancellationToken: CancellationToken.None);
|
||||
|
||||
var found = results.Single(r => r.Id == task.Id).TaskFull!;
|
||||
Assert.Equal(new string('x', 10), found.Description);
|
||||
Assert.True(found.DescriptionTruncated);
|
||||
Assert.Equal(50, found.DescriptionFullLength);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BatchGetTasks_DescriptionUnderCap_IsNotTruncated()
|
||||
{
|
||||
var listId = await SeedListAsync();
|
||||
var task = await SeedTaskAsync(listId);
|
||||
task.Description = "short";
|
||||
await _tasks.UpdateAsync(task);
|
||||
var sut = BuildSut();
|
||||
|
||||
var results = await sut.BatchGetTasks(
|
||||
new[] { task.Id }, includeDescription: true, cancellationToken: CancellationToken.None);
|
||||
|
||||
var found = results.Single(r => r.Id == task.Id).TaskFull!;
|
||||
Assert.Equal("short", found.Description);
|
||||
Assert.False(found.DescriptionTruncated);
|
||||
Assert.Null(found.DescriptionFullLength);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BatchGetTasks_FieldsRestrictsPayload_ToRequestedFieldsOnly()
|
||||
{
|
||||
var listId = await SeedListAsync();
|
||||
var task = await SeedTaskAsync(listId);
|
||||
task.Description = "a description that should not come back when fields excludes it";
|
||||
await _tasks.UpdateAsync(task);
|
||||
var sut = BuildSut();
|
||||
|
||||
var results = await sut.BatchGetTasks(
|
||||
new[] { task.Id }, includeDescription: true, fields: new[] { "title", "status" },
|
||||
cancellationToken: CancellationToken.None);
|
||||
|
||||
var found = results.Single(r => r.Id == task.Id).TaskFull!;
|
||||
Assert.Equal(task.Title, found.Title);
|
||||
Assert.NotNull(found.Status);
|
||||
Assert.Null(found.Description);
|
||||
Assert.Null(found.ListId);
|
||||
Assert.Null(found.RoadblockCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BatchGetTasks_UnknownField_Throws()
|
||||
{
|
||||
var listId = await SeedListAsync();
|
||||
var task = await SeedTaskAsync(listId);
|
||||
var sut = BuildSut();
|
||||
|
||||
var ex = await Assert.ThrowsAsync<InvalidOperationException>(
|
||||
() => sut.BatchGetTasks(
|
||||
new[] { task.Id }, includeDescription: true, fields: new[] { "notAField" },
|
||||
cancellationToken: CancellationToken.None));
|
||||
Assert.Contains("notAField", ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BatchGetTasks_RoadblockTextField_ExtractsTailOfResult_WithoutFullResult()
|
||||
{
|
||||
var listId = await SeedListAsync();
|
||||
var task = await SeedTaskAsync(listId);
|
||||
task.Result = "the task's own result\n\n⚠ Roadblocks reported during the run:\n- missing credentials";
|
||||
await _tasks.UpdateAsync(task);
|
||||
var sut = BuildSut();
|
||||
|
||||
var results = await sut.BatchGetTasks(
|
||||
new[] { task.Id }, includeDescription: true, fields: new[] { "roadblockText" },
|
||||
cancellationToken: CancellationToken.None);
|
||||
|
||||
var found = results.Single(r => r.Id == task.Id).TaskFull!;
|
||||
Assert.Equal("- missing credentials", found.RoadblockText);
|
||||
Assert.Null(found.Result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BatchGetTasks_NoRoadblockMarker_RoadblockTextIsNull()
|
||||
{
|
||||
var listId = await SeedListAsync();
|
||||
var task = await SeedTaskAsync(listId);
|
||||
task.Result = "plain result, no roadblocks";
|
||||
await _tasks.UpdateAsync(task);
|
||||
var sut = BuildSut();
|
||||
|
||||
var results = await sut.BatchGetTasks(
|
||||
new[] { task.Id }, includeDescription: true, fields: new[] { "roadblockText" },
|
||||
cancellationToken: CancellationToken.None);
|
||||
|
||||
Assert.Null(results.Single(r => r.Id == task.Id).TaskFull!.RoadblockText);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BatchGetTasks_OversizedResponse_ThrowsNamingTheFixingParameters()
|
||||
{
|
||||
var listId = await SeedListAsync();
|
||||
var ids = new List<string>();
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
var task = await SeedTaskAsync(listId, $"t{i}");
|
||||
task.Description = new string('d', 6000);
|
||||
await _tasks.UpdateAsync(task);
|
||||
ids.Add(task.Id);
|
||||
}
|
||||
var sut = BuildSut();
|
||||
|
||||
var ex = await Assert.ThrowsAsync<InvalidOperationException>(
|
||||
() => sut.BatchGetTasks(
|
||||
ids.ToArray(), includeDescription: true, descriptionMaxChars: 6000, cancellationToken: CancellationToken.None));
|
||||
Assert.Contains("descriptionMaxChars", ex.Message);
|
||||
Assert.Contains("fields", ex.Message);
|
||||
Assert.Contains("taskIds", ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BatchGetTasks_TenTasksWithDescriptions_StaysWithinTokenBudget()
|
||||
{
|
||||
var listId = await SeedListAsync();
|
||||
var ids = new List<string>();
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
var task = await SeedTaskAsync(listId, $"t{i}");
|
||||
task.Description = new string('d', 5000);
|
||||
await _tasks.UpdateAsync(task);
|
||||
ids.Add(task.Id);
|
||||
}
|
||||
var sut = BuildSut();
|
||||
|
||||
var results = await sut.BatchGetTasks(ids.ToArray(), includeDescription: true, cancellationToken: CancellationToken.None);
|
||||
|
||||
Assert.Equal(10, results.Count);
|
||||
Assert.All(results, r => Assert.True(r.TaskFull!.DescriptionTruncated));
|
||||
var json = System.Text.Json.JsonSerializer.Serialize(results);
|
||||
Assert.True(json.Length < 25_000, $"response was {json.Length} chars, expected < 25000");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BatchDeleteTasks_RunningTask_ReportedNotOk_OthersDeleted()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user