MarketAlly.AIPlugin.Extensions/MarketAlly.AIPlugin.DevOps/Tests/DevOpsScanPluginTests.cs

210 lines
7.1 KiB
C#
Executable File

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 DevOpsScanPluginTests
{
private DevOpsScanPlugin _plugin;
private Mock<ILogger<DevOpsScanPlugin>> _mockLogger;
private string _testDataPath;
[TestInitialize]
public void Setup()
{
_mockLogger = new Mock<ILogger<DevOpsScanPlugin>>();
_plugin = new DevOpsScanPlugin(_mockLogger.Object);
// Find the project directory by traversing up from the assembly location
var assemblyLocation = Path.GetDirectoryName(typeof(DevOpsScanPluginTests).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", "SamplePipelines");
}
[TestMethod]
public async Task ExecuteAsync_GitHubActions_ReturnsValidAnalysis()
{
// Arrange
var githubFile = Path.Combine(_testDataPath, "github-actions-sample.yml");
var parameters = new Dictionary<string, object>
{
["pipelinePath"] = githubFile,
["pipelineType"] = "github",
["checkSecurity"] = true,
["optimizeBuild"] = true,
["checkBestPractices"] = true,
["generateRecommendations"] = true
};
// Act
var result = await _plugin.ExecuteAsync(parameters);
// Assert
Assert.IsTrue(result.Success);
Assert.IsNotNull(result.Data);
var data = result.Data as dynamic;
Assert.IsNotNull(data);
Assert.AreEqual("DevOps pipeline scan completed", data.GetType().GetProperty("Message")?.GetValue(data));
}
[TestMethod]
public async Task ExecuteAsync_NonExistentFile_ReturnsError()
{
// Arrange
var parameters = new Dictionary<string, object>
{
["pipelinePath"] = "/nonexistent/path/pipeline.yml"
};
// Act
var result = await _plugin.ExecuteAsync(parameters);
// Assert
Assert.IsFalse(result.Success);
Assert.IsNotNull(result.Error);
Assert.IsTrue(result.Error is FileNotFoundException);
}
[TestMethod]
public async Task ExecuteAsync_SecurityCheck_DetectsIssues()
{
// Arrange
var tempFile = Path.GetTempFileName();
var insecureContent = @"
name: Insecure Pipeline
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@main
- name: Deploy
env:
API_KEY: ghp_1234567890abcdefghijklmnopqrstuvwxyz12
run: echo 'Deploying'
";
await File.WriteAllTextAsync(tempFile, insecureContent);
var parameters = new Dictionary<string, object>
{
["pipelinePath"] = tempFile,
["pipelineType"] = "github",
["checkSecurity"] = true
};
try
{
// Act
var result = await _plugin.ExecuteAsync(parameters);
// Assert
Assert.IsTrue(result.Success);
var data = result.Data as dynamic;
Assert.IsNotNull(data);
// Should detect security issues
var securityIssues = data.GetType().GetProperty("SecurityIssues")?.GetValue(data) as System.Collections.IList;
Assert.IsNotNull(securityIssues);
Assert.IsTrue(securityIssues.Count > 0);
}
finally
{
if (File.Exists(tempFile))
File.Delete(tempFile);
}
}
[TestMethod]
public void SupportedParameters_ReturnsExpectedParameters()
{
// Act
var parameters = _plugin.SupportedParameters;
// Assert
Assert.IsNotNull(parameters);
Assert.IsTrue(parameters.ContainsKey("pipelinePath"));
Assert.IsTrue(parameters.ContainsKey("pipelineType"));
Assert.IsTrue(parameters.ContainsKey("checkSecurity"));
Assert.IsTrue(parameters.ContainsKey("optimizeBuild"));
Assert.IsTrue(parameters.ContainsKey("checkBestPractices"));
Assert.IsTrue(parameters.ContainsKey("generateRecommendations"));
}
[TestMethod]
public async Task ExecuteAsync_AzureDevOps_ParsesBasicStructure()
{
// Arrange
var azureFile = Path.Combine(_testDataPath, "azure-pipelines-sample.yml");
var parameters = new Dictionary<string, object>
{
["pipelinePath"] = azureFile,
["pipelineType"] = "azure"
};
// Act
var result = await _plugin.ExecuteAsync(parameters);
// Assert
Assert.IsTrue(result.Success);
var data = result.Data as dynamic;
Assert.IsNotNull(data);
Assert.AreEqual("azure", data.GetType().GetProperty("PipelineType")?.GetValue(data));
}
[TestMethod]
public async Task ExecuteAsync_GitLabCI_ParsesBasicStructure()
{
// Arrange
var gitlabFile = Path.Combine(_testDataPath, "gitlab-ci-sample.yml");
var parameters = new Dictionary<string, object>
{
["pipelinePath"] = gitlabFile,
["pipelineType"] = "gitlab"
};
// Act
var result = await _plugin.ExecuteAsync(parameters);
// Assert
Assert.IsTrue(result.Success);
var data = result.Data as dynamic;
Assert.IsNotNull(data);
Assert.AreEqual("gitlab", data.GetType().GetProperty("PipelineType")?.GetValue(data));
}
[TestMethod]
public async Task ExecuteAsync_AutoDetection_DetectsGitHubActions()
{
// Arrange
var githubFile = Path.Combine(_testDataPath, "github-actions-sample.yml");
var parameters = new Dictionary<string, object>
{
["pipelinePath"] = githubFile,
["pipelineType"] = "auto"
};
// Act
var result = await _plugin.ExecuteAsync(parameters);
// Assert
Assert.IsTrue(result.Success);
// Note: Auto-detection would need the file to be in .github/workflows/ directory
// This test validates the auto parameter is handled correctly
}
}
}