using Sdt.Config; using Sdt.Core; using Xunit; namespace DevTool.Tests; public sealed class ConfigDoctorServiceTests { [Fact] public async Task TargetsOnly_Config_IsFlaggedAsFail() { var config = new DevToolConfig { Targets = [ new BuildTarget { Id = "build", Label = "Build", Command = "dotnet", Args = ["build"] } ], Workflows = [] }; var doctor = new ConfigDoctorService(new AlwaysAvailableProbe(), new RequirementResolver()); var report = await doctor.RunAsync(config, Directory.GetCurrentDirectory()); Assert.Contains(report.Checks, c => c.Name == "Legacy schema" && c.Status == DoctorStatus.Fail); } [Fact] public async Task MissingTool_IsReportedWithFix() { var config = new DevToolConfig { Workflows = [ new WorkflowDefinition { Id = "build", Label = "Build", Steps = [ new WorkflowStep { Id = "s1", Label = "Build", Command = "dotnet", Args = ["build"] } ] } ] }; var doctor = new ConfigDoctorService(new AlwaysMissingProbe(), new RequirementResolver()); var report = await doctor.RunAsync(config, Directory.GetCurrentDirectory()); Assert.Contains(report.Checks, c => c.Name.Equals("Tool: dotnet", StringComparison.OrdinalIgnoreCase) && c.Status == DoctorStatus.Fail && !string.IsNullOrWhiteSpace(c.Fix)); } private sealed class AlwaysAvailableProbe : IToolProbe { public Task ProbeAsync( string tool, string projectRoot, DevToolConfig? config = null, IReadOnlyDictionary? envOverrides = null, CancellationToken cancellationToken = default) => Task.FromResult(new ProbeResult(tool, true, Version: "1.0.0")); } private sealed class AlwaysMissingProbe : IToolProbe { public Task ProbeAsync( string tool, string projectRoot, DevToolConfig? config = null, IReadOnlyDictionary? envOverrides = null, CancellationToken cancellationToken = default) => Task.FromResult(new ProbeResult(tool, false, Details: "Fallback: unresolved command")); } }