using System.Text.Json; using ClaudeDo.Data; using ClaudeDo.Data.Models; using Microsoft.EntityFrameworkCore; using TaskStatus = ClaudeDo.Data.Models.TaskStatus; namespace ClaudeDo.Data.Tests; public sealed class SessionSkillsColumnRoundtripTests : IDisposable { private readonly string _dbPath; private readonly ClaudeDoDbContext _ctx; public SessionSkillsColumnRoundtripTests() { _dbPath = Path.Combine(Path.GetTempPath(), $"claudedo_skillscol_{Guid.NewGuid():N}.db"); var options = new DbContextOptionsBuilder() .UseSqlite($"Data Source={_dbPath}") .Options; _ctx = new ClaudeDoDbContext(options); _ctx.Database.EnsureCreated(); } public void Dispose() { _ctx.Dispose(); foreach (var suffix in new[] { "", "-wal", "-shm" }) try { File.Delete(_dbPath + suffix); } catch { } } [Fact] public async Task Task_SessionSkills_json_array_roundtrips() { var names = new List { "a", "b" }; var list = new ListEntity { Id = "l1", Name = "Test", CreatedAt = DateTime.UtcNow }; var task = new TaskEntity { Id = "t1", ListId = "l1", Title = "T", Status = TaskStatus.Idle, CreatedAt = DateTime.UtcNow, SessionSkills = JsonSerializer.Serialize(names), }; _ctx.Lists.Add(list); _ctx.Tasks.Add(task); await _ctx.SaveChangesAsync(); await using var freshCtx = new ClaudeDoDbContext( new DbContextOptionsBuilder().UseSqlite($"Data Source={_dbPath}").Options); var reloaded = await freshCtx.Tasks.AsNoTracking().FirstAsync(t => t.Id == "t1"); var roundtripped = JsonSerializer.Deserialize>(reloaded.SessionSkills!); Assert.Equal(names, roundtripped); } [Fact] public async Task ListConfig_SessionSkills_json_array_roundtrips() { var names = new List { "a", "b" }; var list = new ListEntity { Id = "l1", Name = "Test", CreatedAt = DateTime.UtcNow }; var config = new ListConfigEntity { ListId = "l1", SessionSkills = JsonSerializer.Serialize(names) }; _ctx.Lists.Add(list); _ctx.ListConfigs.Add(config); await _ctx.SaveChangesAsync(); await using var freshCtx = new ClaudeDoDbContext( new DbContextOptionsBuilder().UseSqlite($"Data Source={_dbPath}").Options); var reloaded = await freshCtx.ListConfigs.AsNoTracking().FirstAsync(c => c.ListId == "l1"); var roundtripped = JsonSerializer.Deserialize>(reloaded.SessionSkills!); Assert.Equal(names, roundtripped); } [Fact] public async Task AppSettings_SessionSkills_json_array_roundtrips() { var names = new List { "a", "b" }; var settings = await _ctx.AppSettings.FirstAsync(s => s.Id == AppSettingsEntity.SingletonId); settings.SessionSkills = JsonSerializer.Serialize(names); await _ctx.SaveChangesAsync(); await using var freshCtx = new ClaudeDoDbContext( new DbContextOptionsBuilder().UseSqlite($"Data Source={_dbPath}").Options); var reloaded = await freshCtx.AppSettings.AsNoTracking().FirstAsync(s => s.Id == AppSettingsEntity.SingletonId); var roundtripped = JsonSerializer.Deserialize>(reloaded.SessionSkills!); Assert.Equal(names, roundtripped); } }