test(configmanager): expand unit test coverage to 451 tests
Add comprehensive tests for services (ConnectionTestService, RuntimeConfigValidation), ViewModels (PipelineEditor, dialogs, transformers), and Avalonia headless UI tests for views and forms.
This commit is contained in:
@@ -63,4 +63,175 @@ public class BackupServiceTests
|
||||
// Assert - should delete 5 oldest backups
|
||||
await _fileSystem.Received(5).DeleteFileAsync(Arg.Any<string>(), Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetBackupsAsync_ReturnsBackupsSortedByTimestampDescending()
|
||||
{
|
||||
// Arrange
|
||||
var filePath = "/config/appsettings.json";
|
||||
_fileSystem.GetDirectoryName(filePath).Returns("/config");
|
||||
_fileSystem.GetFileNameWithoutExtension(filePath).Returns("appsettings");
|
||||
|
||||
// Backups in random order
|
||||
var backups = new[]
|
||||
{
|
||||
"/config/appsettings.2026-01-15_120000.bak",
|
||||
"/config/appsettings.2026-01-10_120000.bak",
|
||||
"/config/appsettings.2026-01-20_120000.bak"
|
||||
};
|
||||
_fileSystem.GetFilesAsync("/config", "appsettings.*.bak", Arg.Any<CancellationToken>())
|
||||
.Returns(Task.FromResult(backups));
|
||||
|
||||
// Mock GetFileNameWithoutExtension for each backup file
|
||||
foreach (var backup in backups)
|
||||
{
|
||||
var fileName = backup.Split('/').Last().Replace(".bak", "");
|
||||
_fileSystem.GetFileNameWithoutExtension(backup).Returns(fileName);
|
||||
}
|
||||
|
||||
// Act
|
||||
var result = await _sut.GetBackupsAsync(filePath);
|
||||
|
||||
// Assert
|
||||
result.ShouldNotBeNull();
|
||||
result.Count.ShouldBe(3);
|
||||
|
||||
// Should be sorted descending by timestamp (newest first)
|
||||
result[0].Path.ShouldContain("2026-01-20");
|
||||
result[1].Path.ShouldContain("2026-01-15");
|
||||
result[2].Path.ShouldContain("2026-01-10");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetBackupsAsync_WithNoBackups_ReturnsEmptyList()
|
||||
{
|
||||
// Arrange
|
||||
var filePath = "/config/appsettings.json";
|
||||
_fileSystem.GetDirectoryName(filePath).Returns("/config");
|
||||
_fileSystem.GetFileNameWithoutExtension(filePath).Returns("appsettings");
|
||||
_fileSystem.GetFilesAsync("/config", "appsettings.*.bak", Arg.Any<CancellationToken>())
|
||||
.Returns(Task.FromResult(Array.Empty<string>()));
|
||||
|
||||
// Act
|
||||
var result = await _sut.GetBackupsAsync(filePath);
|
||||
|
||||
// Assert
|
||||
result.ShouldNotBeNull();
|
||||
result.ShouldBeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RestoreBackupAsync_CopiesBackupToTarget()
|
||||
{
|
||||
// Arrange
|
||||
var backupPath = "/config/appsettings.2026-01-15_120000.bak";
|
||||
var targetPath = "/config/appsettings.json";
|
||||
|
||||
// Act
|
||||
await _sut.RestoreBackupAsync(backupPath, targetPath);
|
||||
|
||||
// Assert
|
||||
await _fileSystem.Received(1).CopyFileAsync(backupPath, targetPath, Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CleanupOldBackupsAsync_WithFewerThanKeepCount_DeletesNone()
|
||||
{
|
||||
// Arrange
|
||||
var filePath = "/config/appsettings.json";
|
||||
_fileSystem.GetDirectoryName(filePath).Returns("/config");
|
||||
_fileSystem.GetFileNameWithoutExtension(filePath).Returns("appsettings");
|
||||
|
||||
// Only 3 backups, but keepCount is 10
|
||||
var backups = new[]
|
||||
{
|
||||
"/config/appsettings.2026-01-15_120000.bak",
|
||||
"/config/appsettings.2026-01-16_120000.bak",
|
||||
"/config/appsettings.2026-01-17_120000.bak"
|
||||
};
|
||||
_fileSystem.GetFilesAsync("/config", "appsettings.*.bak", Arg.Any<CancellationToken>())
|
||||
.Returns(Task.FromResult(backups));
|
||||
|
||||
foreach (var backup in backups)
|
||||
{
|
||||
var fileName = backup.Split('/').Last().Replace(".bak", "");
|
||||
_fileSystem.GetFileNameWithoutExtension(backup).Returns(fileName);
|
||||
}
|
||||
|
||||
// Act
|
||||
await _sut.CleanupOldBackupsAsync(filePath, keepCount: 10);
|
||||
|
||||
// Assert - no files should be deleted
|
||||
await _fileSystem.DidNotReceive().DeleteFileAsync(Arg.Any<string>(), Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateBackupAsync_WithNonExistentFile_ThrowsFileNotFoundException()
|
||||
{
|
||||
// Arrange
|
||||
var sourcePath = "/config/nonexistent.json";
|
||||
_fileSystem.FileExists(sourcePath).Returns(false);
|
||||
|
||||
// Act & Assert
|
||||
await Should.ThrowAsync<FileNotFoundException>(
|
||||
() => _sut.CreateBackupAsync(sourcePath));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetBackupsAsync_SkipsFilesWithInvalidTimestampFormat()
|
||||
{
|
||||
// Arrange
|
||||
var filePath = "/config/appsettings.json";
|
||||
_fileSystem.GetDirectoryName(filePath).Returns("/config");
|
||||
_fileSystem.GetFileNameWithoutExtension(filePath).Returns("appsettings");
|
||||
|
||||
// Mix of valid and invalid backup filenames
|
||||
var backups = new[]
|
||||
{
|
||||
"/config/appsettings.2026-01-15_120000.bak", // Valid
|
||||
"/config/appsettings.invalid-format.bak", // Invalid
|
||||
"/config/appsettings.2026-01-16_120000.bak" // Valid
|
||||
};
|
||||
_fileSystem.GetFilesAsync("/config", "appsettings.*.bak", Arg.Any<CancellationToken>())
|
||||
.Returns(Task.FromResult(backups));
|
||||
|
||||
_fileSystem.GetFileNameWithoutExtension(backups[0]).Returns("appsettings.2026-01-15_120000");
|
||||
_fileSystem.GetFileNameWithoutExtension(backups[1]).Returns("appsettings.invalid-format");
|
||||
_fileSystem.GetFileNameWithoutExtension(backups[2]).Returns("appsettings.2026-01-16_120000");
|
||||
|
||||
// Act
|
||||
var result = await _sut.GetBackupsAsync(filePath);
|
||||
|
||||
// Assert
|
||||
result.ShouldNotBeNull();
|
||||
result.Count.ShouldBe(2); // Only valid backups
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CleanupOldBackupsAsync_WithExactKeepCount_DeletesNone()
|
||||
{
|
||||
// Arrange
|
||||
var filePath = "/config/appsettings.json";
|
||||
_fileSystem.GetDirectoryName(filePath).Returns("/config");
|
||||
_fileSystem.GetFileNameWithoutExtension(filePath).Returns("appsettings");
|
||||
|
||||
// Exactly 5 backups with keepCount of 5
|
||||
var backups = Enumerable.Range(1, 5)
|
||||
.Select(i => $"/config/appsettings.2026-01-{i:D2}_120000.bak")
|
||||
.ToArray();
|
||||
_fileSystem.GetFilesAsync("/config", "appsettings.*.bak", Arg.Any<CancellationToken>())
|
||||
.Returns(Task.FromResult(backups));
|
||||
|
||||
foreach (var backup in backups)
|
||||
{
|
||||
var fileName = backup.Split('/').Last().Replace(".bak", "");
|
||||
_fileSystem.GetFileNameWithoutExtension(backup).Returns(fileName);
|
||||
}
|
||||
|
||||
// Act
|
||||
await _sut.CleanupOldBackupsAsync(filePath, keepCount: 5);
|
||||
|
||||
// Assert - no files should be deleted
|
||||
await _fileSystem.DidNotReceive().DeleteFileAsync(Arg.Any<string>(), Arg.Any<CancellationToken>());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user