using ClaudeDo.Data; using ClaudeDo.Data.Models; using ClaudeDo.Data.Repositories; using Microsoft.EntityFrameworkCore; namespace ClaudeDo.Data.Tests; public sealed class PowerUseTests : IDisposable { private readonly string _dbPath; private readonly ClaudeDoDbContext _ctx; private const string ListId = "l1"; public PowerUseTests() { _dbPath = Path.Combine(Path.GetTempPath(), $"claudedo_poweruse_{Guid.NewGuid():N}.db"); var options = new DbContextOptionsBuilder() .UseSqlite($"Data Source={_dbPath}") .Options; _ctx = new ClaudeDoDbContext(options); _ctx.Database.EnsureCreated(); _ctx.Lists.Add(new ListEntity { Id = ListId, Name = "Test", CreatedAt = DateTime.UtcNow }); _ctx.SaveChanges(); } public void Dispose() { _ctx.Dispose(); foreach (var suffix in new[] { "", "-wal", "-shm" }) try { File.Delete(_dbPath + suffix); } catch { } } private ClaudeDoDbContext Reload() => new( new DbContextOptionsBuilder() .UseSqlite(_ctx.Database.GetConnectionString()).Options); [Fact] public async Task ListConfig_PowerUseAllowed_DefaultsToFalse() { await new ListRepository(_ctx).SetConfigAsync(new ListConfigEntity { ListId = ListId, Model = "sonnet" }); using var reload = Reload(); var cfg = await new ListRepository(reload).GetConfigAsync(ListId); Assert.False(cfg!.PowerUseAllowed); } [Fact] public async Task ListConfig_PowerUseAllowed_RoundtripsTrue() { await new ListRepository(_ctx).SetConfigAsync(new ListConfigEntity { ListId = ListId, PowerUseAllowed = true }); using var reload = Reload(); var cfg = await new ListRepository(reload).GetConfigAsync(ListId); Assert.True(cfg!.PowerUseAllowed); } /// SetConfigAsync copies the incoming entity field by field onto the existing row. A field /// forgotten in that copy block reads as "silently reset on the next unrelated save", which is /// exactly how the ticket-project link broke before. Pin it for PowerUseAllowed. [Fact] public async Task ListConfig_UpdatingAnotherField_DoesNotResetPowerUseAllowed() { var repo = new ListRepository(_ctx); await repo.SetConfigAsync(new ListConfigEntity { ListId = ListId, PowerUseAllowed = true }); await repo.SetConfigAsync(new ListConfigEntity { ListId = ListId, PowerUseAllowed = true, VerifyCommand = "dotnet build" }); using var reload = Reload(); var cfg = await new ListRepository(reload).GetConfigAsync(ListId); Assert.True(cfg!.PowerUseAllowed); Assert.Equal("dotnet build", cfg.VerifyCommand); } [Fact] public async Task AppSettings_PowerUseDefaults_AreOffAndFourHandoffs() { var settings = await new AppSettingsRepository(_ctx).GetAsync(); Assert.False(settings.PowerUseEnabled); Assert.Equal(4, settings.ListHandlerMaxHandoffs); } [Fact] public async Task AppSettings_PowerUseFields_Roundtrip() { await new AppSettingsRepository(_ctx).GetAsync(); var row = await _ctx.AppSettings.FirstAsync(s => s.Id == AppSettingsEntity.SingletonId); row.PowerUseEnabled = true; row.ListHandlerMaxHandoffs = 40; await _ctx.SaveChangesAsync(); using var reload = Reload(); var settings = await new AppSettingsRepository(reload).GetAsync(); Assert.True(settings.PowerUseEnabled); Assert.Equal(40, settings.ListHandlerMaxHandoffs); } }