using ClaudeDo.Data;
using ClaudeDo.Data.Models;
using ClaudeDo.Data.Repositories;
using Microsoft.EntityFrameworkCore;
using TaskStatus = ClaudeDo.Data.Models.TaskStatus;
namespace ClaudeDo.Data.Tests;
///
/// Verifies that TaskRepository.DeleteAsync and ListRepository.DeleteAsync
/// delete the on-disk attachment directories for the affected tasks.
///
public sealed class RepositoryAttachmentCleanupTests : IDisposable
{
private readonly string _dbPath;
private readonly string _attachRoot;
private readonly ClaudeDoDbContext _ctx;
private readonly AttachmentStore _store;
public RepositoryAttachmentCleanupTests()
{
_dbPath = Path.Combine(Path.GetTempPath(), $"claudedo_repoclean_{Guid.NewGuid():N}.db");
_attachRoot = Path.Combine(Path.GetTempPath(), $"claudedo_repoclean_att_{Guid.NewGuid():N}");
Directory.CreateDirectory(_attachRoot);
var options = new DbContextOptionsBuilder()
.UseSqlite($"Data Source={_dbPath}")
.Options;
_ctx = new ClaudeDoDbContext(options);
_ctx.Database.EnsureCreated();
_store = new AttachmentStore(_attachRoot);
}
public void Dispose()
{
_ctx.Dispose();
foreach (var suffix in new[] { "", "-wal", "-shm" })
try { File.Delete(_dbPath + suffix); } catch { }
try { Directory.Delete(_attachRoot, recursive: true); } catch { }
}
private async Task<(string listId, string taskId)> SeedAsync()
{
var listId = Guid.NewGuid().ToString();
var taskId = Guid.NewGuid().ToString();
_ctx.Lists.Add(new ListEntity { Id = listId, Name = "L", CreatedAt = DateTime.UtcNow });
_ctx.Tasks.Add(new TaskEntity
{
Id = taskId, ListId = listId, Title = "T",
Status = TaskStatus.Idle, CreatedAt = DateTime.UtcNow,
});
await _ctx.SaveChangesAsync();
return (listId, taskId);
}
[Fact]
public async Task TaskRepository_DeleteAsync_RemovesAttachmentDir()
{
var (_, taskId) = await SeedAsync();
var taskDir = _store.TaskDir(taskId);
Directory.CreateDirectory(taskDir);
Assert.True(Directory.Exists(taskDir));
var repo = new TaskRepository(_ctx, _store);
await repo.DeleteAsync(taskId);
Assert.False(Directory.Exists(taskDir));
}
[Fact]
public async Task ListRepository_DeleteAsync_RemovesAttachmentDirForEachTask()
{
var (listId, taskId) = await SeedAsync();
var taskDir = _store.TaskDir(taskId);
Directory.CreateDirectory(taskDir);
Assert.True(Directory.Exists(taskDir));
var repo = new ListRepository(_ctx, _store);
await repo.DeleteAsync(listId);
Assert.False(Directory.Exists(taskDir));
}
}