using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.Extensions.Logging; using MarketAlly.AIPlugin.DevOps.Plugins; using System; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using Moq; namespace MarketAlly.AIPlugin.DevOps.Tests { [TestClass] public class ConfigurationAnalyzerPluginTests { private ConfigurationAnalyzerPlugin _plugin; private Mock> _mockLogger; private string _testDataPath; [TestInitialize] public void Setup() { _mockLogger = new Mock>(); _plugin = new ConfigurationAnalyzerPlugin(_mockLogger.Object); // Find the project directory by traversing up from the assembly location var assemblyLocation = Path.GetDirectoryName(typeof(ConfigurationAnalyzerPluginTests).Assembly.Location); var projectDir = assemblyLocation; while (projectDir != null && !Directory.Exists(Path.Combine(projectDir, "Tests", "TestData"))) { projectDir = Directory.GetParent(projectDir)?.FullName; } _testDataPath = Path.Combine(projectDir ?? assemblyLocation, "Tests", "TestData", "SampleConfigs"); } [TestMethod] public async Task ExecuteAsync_ValidConfigDirectory_ReturnsAnalysis() { // Arrange var parameters = new Dictionary { ["configDirectory"] = _testDataPath, ["checkDrift"] = true, ["validateEnvironments"] = true, ["checkSettings"] = true }; // Act var result = await _plugin.ExecuteAsync(parameters); // Assert Assert.IsTrue(result.Success, $"Plugin execution failed with message: {result.Error?.Message}"); var data = result.Data as dynamic; Assert.IsNotNull(data); Assert.AreEqual("Configuration analysis completed", data.GetType().GetProperty("Message")?.GetValue(data)); } [TestMethod] public async Task ExecuteAsync_NonExistentDirectory_ReturnsError() { // Arrange var parameters = new Dictionary { ["configDirectory"] = "/nonexistent/directory" }; // Act var result = await _plugin.ExecuteAsync(parameters); // Assert Assert.IsFalse(result.Success); Assert.IsNotNull(result.Error); Assert.IsTrue(result.Error is DirectoryNotFoundException); } [TestMethod] public async Task ExecuteAsync_ConfigurationDrift_DetectsDifferences() { // Arrange var parameters = new Dictionary { ["configDirectory"] = _testDataPath, ["checkDrift"] = true }; // Act var result = await _plugin.ExecuteAsync(parameters); // Assert Assert.IsTrue(result.Success); var data = result.Data as dynamic; Assert.IsNotNull(data); var configurationDrift = data.GetType().GetProperty("ConfigurationDrift")?.GetValue(data) as System.Collections.IList; Assert.IsNotNull(configurationDrift); // Should detect drift between Development and Production configs Assert.IsTrue(configurationDrift.Count > 0); } [TestMethod] public async Task ExecuteAsync_SecurityIssues_DetectsInsecureConfigs() { // Arrange var parameters = new Dictionary { ["configDirectory"] = _testDataPath, ["filePatterns"] = "*.yml" }; // Act var result = await _plugin.ExecuteAsync(parameters); // Assert Assert.IsTrue(result.Success); var data = result.Data as dynamic; Assert.IsNotNull(data); var securityIssues = data.GetType().GetProperty("SecurityIssues")?.GetValue(data) as System.Collections.IList; Assert.IsNotNull(securityIssues); // Should detect hardcoded secrets in config.insecure.yml Assert.IsTrue(securityIssues.Count > 0); } [TestMethod] public async Task ExecuteAsync_EnvironmentValidation_DetectsIssues() { // Arrange var parameters = new Dictionary { ["configDirectory"] = _testDataPath, ["validateEnvironments"] = true }; // Act var result = await _plugin.ExecuteAsync(parameters); // Assert Assert.IsTrue(result.Success); var data = result.Data as dynamic; Assert.IsNotNull(data); var environmentIssues = data.GetType().GetProperty("EnvironmentIssues")?.GetValue(data) as System.Collections.IList; Assert.IsNotNull(environmentIssues); } [TestMethod] public async Task ExecuteAsync_GenerateDocumentation_ReturnsDocumentation() { // Arrange var parameters = new Dictionary { ["configDirectory"] = _testDataPath, ["generateDocumentation"] = true }; // Act var result = await _plugin.ExecuteAsync(parameters); // Assert Assert.IsTrue(result.Success); var data = result.Data as dynamic; Assert.IsNotNull(data); var documentation = data.GetType().GetProperty("Documentation")?.GetValue(data) as string; Assert.IsNotNull(documentation); Assert.IsTrue(documentation.Contains("Configuration Analysis Documentation")); } [TestMethod] public void SupportedParameters_ReturnsExpectedParameters() { // Act var parameters = _plugin.SupportedParameters; // Assert Assert.IsNotNull(parameters); Assert.IsTrue(parameters.ContainsKey("configDirectory")); Assert.IsTrue(parameters.ContainsKey("filePatterns")); Assert.IsTrue(parameters.ContainsKey("checkDrift")); Assert.IsTrue(parameters.ContainsKey("validateEnvironments")); Assert.IsTrue(parameters.ContainsKey("checkSettings")); Assert.IsTrue(parameters.ContainsKey("generateDocumentation")); } [TestMethod] public async Task ExecuteAsync_CustomFilePatterns_AnalyzesSpecificFiles() { // Arrange var parameters = new Dictionary { ["configDirectory"] = _testDataPath, ["filePatterns"] = "*.json" }; // Act var result = await _plugin.ExecuteAsync(parameters); // Assert Assert.IsTrue(result.Success); var data = result.Data as dynamic; Assert.IsNotNull(data); var filesAnalyzed = (int)data.GetType().GetProperty("FilesAnalyzed")?.GetValue(data); Assert.IsTrue(filesAnalyzed >= 2); // Should find at least the two appsettings files } [TestMethod] public async Task ExecuteAsync_CalculatesOverallScore() { // Arrange var parameters = new Dictionary { ["configDirectory"] = _testDataPath }; // Act var result = await _plugin.ExecuteAsync(parameters); // Assert Assert.IsTrue(result.Success); var data = result.Data as dynamic; Assert.IsNotNull(data); var summary = data.GetType().GetProperty("Summary")?.GetValue(data); Assert.IsNotNull(summary); var overallScore = (int)summary.GetType().GetProperty("OverallScore")?.GetValue(summary); Assert.IsTrue(overallScore >= 0 && overallScore <= 100); } } }