Agents can write into the user's daily notes, but only within limits: max 10 agent notes a day, max 500 characters, add only — no edit, no delete. A new from_agent column separates their lines from the user's so the cap counts the right ones and the UI can mark them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
78 lines
2.7 KiB
C#
78 lines
2.7 KiB
C#
using ClaudeDo.Data;
|
|
using ClaudeDo.Data.Repositories;
|
|
using ClaudeDo.Worker.External;
|
|
using ClaudeDo.Worker.Hub;
|
|
using ClaudeDo.Worker.Tests.Infrastructure;
|
|
|
|
namespace ClaudeDo.Worker.Tests.External;
|
|
|
|
public sealed class NotesMcpToolsTests : IDisposable
|
|
{
|
|
private readonly DbFixture _db = new();
|
|
private readonly ClaudeDoDbContext _ctx;
|
|
private readonly DailyNoteRepository _notes;
|
|
private readonly NotesMcpTools _sut;
|
|
private static readonly DateOnly Today = DateOnly.FromDateTime(DateTime.Today);
|
|
|
|
public NotesMcpToolsTests()
|
|
{
|
|
_ctx = _db.CreateContext();
|
|
_notes = new DailyNoteRepository(_ctx);
|
|
_sut = new NotesMcpTools(_notes, new HubBroadcaster(new CapturingHubContext()));
|
|
}
|
|
|
|
public void Dispose() { _ctx.Dispose(); _db.Dispose(); }
|
|
|
|
[Fact]
|
|
public async Task AddNote_stores_it_on_today_flagged_as_agent_written()
|
|
{
|
|
var result = await _sut.AddNote(" Mika decided to keep the daily grouping. ");
|
|
|
|
Assert.True(result.Saved);
|
|
var row = Assert.Single(await _notes.ListByDayAsync(Today));
|
|
Assert.Equal("Mika decided to keep the daily grouping.", row.Text);
|
|
Assert.True(row.FromAgent);
|
|
Assert.Equal(NotesMcpTools.DailyAgentCap - 1, result.RemainingToday);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task AddNote_refuses_once_the_daily_cap_is_used_up_and_saves_nothing()
|
|
{
|
|
for (var i = 0; i < NotesMcpTools.DailyAgentCap; i++)
|
|
await _sut.AddNote($"note {i}");
|
|
|
|
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => _sut.AddNote("one too many"));
|
|
|
|
Assert.Contains("cap", ex.Message, StringComparison.OrdinalIgnoreCase);
|
|
Assert.Equal(NotesMcpTools.DailyAgentCap, (await _notes.ListByDayAsync(Today)).Count);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Notes_the_user_wrote_do_not_count_against_the_agent_cap()
|
|
{
|
|
for (var i = 0; i < NotesMcpTools.DailyAgentCap; i++)
|
|
await _notes.AddAsync(Today, $"mine {i}");
|
|
|
|
var result = await _sut.AddNote("still allowed");
|
|
|
|
Assert.Equal(1, result.AgentNotesToday);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("")]
|
|
[InlineData(" ")]
|
|
public async Task AddNote_rejects_empty_text(string text) =>
|
|
await Assert.ThrowsAsync<InvalidOperationException>(() => _sut.AddNote(text));
|
|
|
|
[Fact]
|
|
public async Task AddNote_rejects_text_past_the_length_limit()
|
|
{
|
|
var tooLong = new string('x', NotesMcpTools.MaxLength + 1);
|
|
|
|
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => _sut.AddNote(tooLong));
|
|
|
|
Assert.Contains(NotesMcpTools.MaxLength.ToString(), ex.Message);
|
|
Assert.Empty(await _notes.ListByDayAsync(Today));
|
|
}
|
|
}
|