using Microsoft.Extensions.Logging; using SolutionCleanupTool.Models; using SolutionCleanupTool.Services; using System; using System.IO; using System.Linq; using Xunit; namespace SolutionCleanupTool.Tests { /// /// Unit tests for SolutionParser functionality /// public class SolutionParserTests : IDisposable { private readonly SolutionParser _parser; private readonly string _tempDirectory; private readonly ILogger _logger; public SolutionParserTests() { // Create a mock logger for testing var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()); _logger = loggerFactory.CreateLogger(); _parser = new SolutionParser(_logger); // Create a temporary directory for test files _tempDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(_tempDirectory); } [Fact] public void ParseSolution_WithValidSolutionFile_ShouldReturnSolutionModel() { // Arrange var solutionContent = @" Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.30114.105 MinimumVisualStudioVersion = 10.0.40219.1 Project(""{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"") = ""TestProject1"", ""TestProject1\TestProject1.csproj"", ""{12345678-1234-1234-1234-123456789012}"" EndProject Project(""{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"") = ""TestProject2"", ""TestProject2\TestProject2.csproj"", ""{87654321-4321-4321-4321-210987654321}"" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {12345678-1234-1234-1234-123456789012}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {12345678-1234-1234-1234-123456789012}.Debug|Any CPU.Build.0 = Debug|Any CPU EndGlobalSection EndGlobal "; var solutionPath = Path.Combine(_tempDirectory, "TestSolution.sln"); File.WriteAllText(solutionPath, solutionContent); // Act var result = _parser.ParseSolution(solutionPath); // Assert Assert.NotNull(result); Assert.Equal(solutionPath, result.FilePath); Assert.Equal(2, result.Projects.Count); var project1 = result.Projects.FirstOrDefault(p => p.Name == "TestProject1"); Assert.NotNull(project1); Assert.Equal("TestProject1\\TestProject1.csproj", project1.RelativePath); Assert.Equal(new Guid("12345678-1234-1234-1234-123456789012"), project1.ProjectGuid); var project2 = result.Projects.FirstOrDefault(p => p.Name == "TestProject2"); Assert.NotNull(project2); Assert.Equal("TestProject2\\TestProject2.csproj", project2.RelativePath); Assert.Equal(new Guid("87654321-4321-4321-4321-210987654321"), project2.ProjectGuid); } [Fact] public void ParseSolution_WithNonExistentFile_ShouldThrowFileNotFoundException() { // Arrange var nonExistentPath = Path.Combine(_tempDirectory, "NonExistent.sln"); // Act & Assert Assert.Throws(() => _parser.ParseSolution(nonExistentPath)); } [Fact] public void ParseSolution_WithNullPath_ShouldThrowArgumentException() { // Act & Assert Assert.Throws(() => _parser.ParseSolution(null)); } [Fact] public void ParseSolution_WithEmptyPath_ShouldThrowArgumentException() { // Act & Assert Assert.Throws(() => _parser.ParseSolution(string.Empty)); } [Fact] public void ExtractProjectReferences_WithValidSolution_ShouldReturnProjectReferences() { // Arrange var solution = new SolutionModel { FilePath = "TestSolution.sln", Projects = new List { new ProjectReference { Name = "TestProject1", RelativePath = "TestProject1\\TestProject1.csproj", AbsolutePath = Path.Combine(_tempDirectory, "TestProject1", "TestProject1.csproj"), ProjectGuid = Guid.NewGuid(), ProjectTypeGuid = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}" } } }; // Act var result = _parser.ExtractProjectReferences(solution); // Assert Assert.NotNull(result); Assert.Single(result); Assert.Equal("TestProject1", result[0].Name); Assert.False(result[0].Exists); // File doesn't exist in temp directory } [Fact] public void ExtractProjectReferences_WithNullSolution_ShouldThrowArgumentNullException() { // Act & Assert Assert.Throws(() => _parser.ExtractProjectReferences(null)); } [Fact] public void ParseSolution_WithSolutionFolders_ShouldIgnoreSolutionFolders() { // Arrange var solutionContent = @" Microsoft Visual Studio Solution File, Format Version 12.00 Project(""{2150E333-8FDC-42A3-9474-1A3956D46DE8}"") = ""SolutionFolder"", ""SolutionFolder"", ""{FOLDER-GUID-1234-1234-1234-123456789012}"" EndProject Project(""{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"") = ""RealProject"", ""RealProject\RealProject.csproj"", ""{12345678-1234-1234-1234-123456789012}"" EndProject Global EndGlobal "; var solutionPath = Path.Combine(_tempDirectory, "TestSolutionWithFolders.sln"); File.WriteAllText(solutionPath, solutionContent); // Act var result = _parser.ParseSolution(solutionPath); // Assert Assert.NotNull(result); Assert.Single(result.Projects); // Should only have the real project, not the solution folder Assert.Equal("RealProject", result.Projects[0].Name); } public void Dispose() { // Clean up temporary directory if (Directory.Exists(_tempDirectory)) { Directory.Delete(_tempDirectory, true); } } } }