using FluentAssertions; using FreeCode.Tools; using FreeCode.Tests.Unit.Helpers; using Xunit; namespace FreeCode.Tests.Unit.Tools; public sealed class FileEditToolTests : IDisposable { private readonly string _tempDirectory = Path.Combine(Path.GetTempPath(), "free-code-tests", Guid.NewGuid().ToString("N")); private readonly FileEditTool _sut = new(); public FileEditToolTests() { Directory.CreateDirectory(_tempDirectory); } [Fact] public async Task ExecuteAsync_ReplacesExistingString() { var path = Path.Combine(_tempDirectory, "sample.txt"); await File.WriteAllTextAsync(path, "before world after"); var result = await _sut.ExecuteAsync(new FileEditToolInput(path, "world", "planet"), TestHelper.CreateContext()); result.IsError.Should().BeFalse(); (await File.ReadAllTextAsync(path)).Should().Be("before planet after"); } [Fact] public async Task ExecuteAsync_WhenOldStringNotFound_ReturnsError() { var path = Path.Combine(_tempDirectory, "sample.txt"); await File.WriteAllTextAsync(path, "content"); var result = await _sut.ExecuteAsync(new FileEditToolInput(path, "missing", "new"), TestHelper.CreateContext()); result.IsError.Should().BeTrue(); result.ErrorMessage.Should().Be("OldString not found."); } [Fact] public async Task ValidateInputAsync_WithNullLikeFields_IsInvalid() { var result = await _sut.ValidateInputAsync(new FileEditToolInput(string.Empty, string.Empty, "value")); result.IsValid.Should().BeFalse(); result.Errors.Should().Contain(["FilePath is required.", "OldString is required."]); } public void Dispose() { if (Directory.Exists(_tempDirectory)) { Directory.Delete(_tempDirectory, recursive: true); } } }