feat(data): store ssh workspaces on app_settings
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
using ClaudeDo.Data;
|
||||
using ClaudeDo.Data.Models;
|
||||
using ClaudeDo.Data.Repositories;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace ClaudeDo.Data.Tests;
|
||||
|
||||
public sealed class SshWorkspaceTests : IDisposable
|
||||
{
|
||||
private readonly string _dbPath;
|
||||
private readonly DbContextOptions<ClaudeDoDbContext> _options;
|
||||
|
||||
public SshWorkspaceTests()
|
||||
{
|
||||
_dbPath = Path.Combine(Path.GetTempPath(), $"claudedo_ssh_{Guid.NewGuid():N}.db");
|
||||
_options = new DbContextOptionsBuilder<ClaudeDoDbContext>().UseSqlite($"Data Source={_dbPath}").Options;
|
||||
using var ctx = new ClaudeDoDbContext(_options);
|
||||
ctx.Database.EnsureCreated();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var suffix in new[] { "", "-wal", "-shm" })
|
||||
try { File.Delete(_dbPath + suffix); } catch { }
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("VPS", "vps", "/home/mika/app", null)]
|
||||
[InlineData("VPS", "mika@vps.example.com", "~/app", null)]
|
||||
[InlineData("VPS", "vps", "~", null)]
|
||||
[InlineData("", "vps", "/x", "name")]
|
||||
[InlineData("VPS", "", "/x", "host")]
|
||||
[InlineData("VPS", "-oProxyCommand=calc", "/x", "host")]
|
||||
[InlineData("VPS", "vps host", "/x", "host")]
|
||||
[InlineData("VPS", "vps", "relative/path", "path")]
|
||||
[InlineData("VPS", "vps", "/it's", "path")]
|
||||
[InlineData("VPS", "vps", "/a\nb", "path")]
|
||||
public void Validate_ReturnsFieldOfFirstProblem(string name, string host, string path, string? expected)
|
||||
=> Assert.Equal(expected, SshWorkspace.Validate(new SshWorkspace("id", name, host, path)));
|
||||
|
||||
[Theory]
|
||||
[InlineData("/home/mika/app", "'/home/mika/app'")]
|
||||
[InlineData("~", "~")]
|
||||
[InlineData("~/app dir", "~/'app dir'")]
|
||||
public void QuoteRemotePath_KeepsTildeExpandable(string path, string expected)
|
||||
=> Assert.Equal(expected, SshWorkspace.QuoteRemotePath(path));
|
||||
|
||||
[Fact]
|
||||
public async Task SetThenGet_RoundTrips_AndSurvivesGeneralSettingsUpdate()
|
||||
{
|
||||
var ws = new SshWorkspace("w1", "VPS", "vps", "/srv/app");
|
||||
await using (var ctx = new ClaudeDoDbContext(_options))
|
||||
await new AppSettingsRepository(ctx).SetSshWorkspacesAsync([ws]);
|
||||
|
||||
// A general settings save copies named fields only; it must not clobber the workspaces.
|
||||
await using (var ctx = new ClaudeDoDbContext(_options))
|
||||
await new AppSettingsRepository(ctx).UpdateAsync(new AppSettingsEntity());
|
||||
|
||||
await using (var ctx = new ClaudeDoDbContext(_options))
|
||||
Assert.Equal([ws], await new AppSettingsRepository(ctx).GetSshWorkspacesAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Get_WithCorruptJson_ReturnsEmpty()
|
||||
{
|
||||
await using (var ctx = new ClaudeDoDbContext(_options))
|
||||
{
|
||||
await new AppSettingsRepository(ctx).GetAsync();
|
||||
await ctx.Database.ExecuteSqlRawAsync("UPDATE app_settings SET ssh_workspaces = 'not json'");
|
||||
}
|
||||
await using (var ctx = new ClaudeDoDbContext(_options))
|
||||
Assert.Empty(await new AppSettingsRepository(ctx).GetSshWorkspacesAsync());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user