Fix build and code structure improvements. New but essential UI functionality. CI improvements. Documentation improvements. AI module improvements.
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
using System.Reflection;
|
||||
using StellaOps.Plugin.Versioning;
|
||||
|
||||
namespace StellaOps.Plugin.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Unit tests for PluginCompatibilityChecker.
|
||||
/// </summary>
|
||||
public sealed class PluginCompatibilityCheckerTests
|
||||
{
|
||||
#region Basic Compatibility Tests
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void CheckCompatibility_AssemblyWithoutAttribute_Lenient_ReturnsCompatible()
|
||||
{
|
||||
// Arrange - Use current test assembly which doesn't have StellaPluginVersionAttribute
|
||||
var assembly = typeof(PluginCompatibilityCheckerTests).Assembly;
|
||||
var hostVersion = new Version(1, 0, 0);
|
||||
|
||||
// Act
|
||||
var result = PluginCompatibilityChecker.CheckCompatibility(
|
||||
assembly, hostVersion, CompatibilityCheckOptions.Lenient);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsCompatible);
|
||||
Assert.False(result.HasVersionAttribute);
|
||||
Assert.Null(result.PluginVersion);
|
||||
}
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void CheckCompatibility_AssemblyWithoutAttribute_RequireVersion_ReturnsIncompatible()
|
||||
{
|
||||
// Arrange
|
||||
var assembly = typeof(PluginCompatibilityCheckerTests).Assembly;
|
||||
var hostVersion = new Version(1, 0, 0);
|
||||
var options = new CompatibilityCheckOptions
|
||||
{
|
||||
RequireVersionAttribute = true
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = PluginCompatibilityChecker.CheckCompatibility(assembly, hostVersion, options);
|
||||
|
||||
// Assert
|
||||
Assert.False(result.IsCompatible);
|
||||
Assert.False(result.HasVersionAttribute);
|
||||
Assert.NotNull(result.FailureReason);
|
||||
Assert.Contains("StellaPluginVersion", result.FailureReason);
|
||||
}
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void CheckCompatibility_NullAssembly_ThrowsException()
|
||||
{
|
||||
// Arrange
|
||||
var hostVersion = new Version(1, 0, 0);
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentNullException>(
|
||||
() => PluginCompatibilityChecker.CheckCompatibility(null!, hostVersion));
|
||||
}
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void CheckCompatibility_NullHostVersion_ThrowsException()
|
||||
{
|
||||
// Arrange
|
||||
var assembly = typeof(PluginCompatibilityCheckerTests).Assembly;
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentNullException>(
|
||||
() => PluginCompatibilityChecker.CheckCompatibility(assembly, null!));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CompatibilityCheckOptions Tests
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void DefaultOptions_HasCorrectValues()
|
||||
{
|
||||
// Act
|
||||
var options = CompatibilityCheckOptions.Default;
|
||||
|
||||
// Assert
|
||||
Assert.True(options.RequireVersionAttribute);
|
||||
Assert.True(options.StrictMajorVersionCheck);
|
||||
}
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void LenientOptions_HasCorrectValues()
|
||||
{
|
||||
// Act
|
||||
var options = CompatibilityCheckOptions.Lenient;
|
||||
|
||||
// Assert
|
||||
Assert.False(options.RequireVersionAttribute);
|
||||
Assert.False(options.StrictMajorVersionCheck);
|
||||
}
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void CustomOptions_CanBeConfigured()
|
||||
{
|
||||
// Arrange & Act
|
||||
var options = new CompatibilityCheckOptions
|
||||
{
|
||||
RequireVersionAttribute = true,
|
||||
StrictMajorVersionCheck = false
|
||||
};
|
||||
|
||||
// Assert
|
||||
Assert.True(options.RequireVersionAttribute);
|
||||
Assert.False(options.StrictMajorVersionCheck);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region PluginCompatibilityResult Tests
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void PluginCompatibilityResult_RecordEquality()
|
||||
{
|
||||
// Arrange
|
||||
var result1 = new PluginCompatibilityResult(
|
||||
IsCompatible: true,
|
||||
PluginVersion: new Version(1, 0, 0),
|
||||
MinimumHostVersion: new Version(1, 0, 0),
|
||||
MaximumHostVersion: new Version(2, 0, 0),
|
||||
RequiresSignature: true,
|
||||
FailureReason: null,
|
||||
HasVersionAttribute: true);
|
||||
|
||||
var result2 = new PluginCompatibilityResult(
|
||||
IsCompatible: true,
|
||||
PluginVersion: new Version(1, 0, 0),
|
||||
MinimumHostVersion: new Version(1, 0, 0),
|
||||
MaximumHostVersion: new Version(2, 0, 0),
|
||||
RequiresSignature: true,
|
||||
FailureReason: null,
|
||||
HasVersionAttribute: true);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(result1, result2);
|
||||
}
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void PluginCompatibilityResult_PropertiesAreSet()
|
||||
{
|
||||
// Arrange
|
||||
var pluginVersion = new Version(1, 2, 3);
|
||||
var minVersion = new Version(1, 0, 0);
|
||||
var maxVersion = new Version(2, 0, 0);
|
||||
var failureReason = "Test failure";
|
||||
|
||||
// Act
|
||||
var result = new PluginCompatibilityResult(
|
||||
IsCompatible: false,
|
||||
PluginVersion: pluginVersion,
|
||||
MinimumHostVersion: minVersion,
|
||||
MaximumHostVersion: maxVersion,
|
||||
RequiresSignature: true,
|
||||
FailureReason: failureReason,
|
||||
HasVersionAttribute: true);
|
||||
|
||||
// Assert
|
||||
Assert.False(result.IsCompatible);
|
||||
Assert.Equal(pluginVersion, result.PluginVersion);
|
||||
Assert.Equal(minVersion, result.MinimumHostVersion);
|
||||
Assert.Equal(maxVersion, result.MaximumHostVersion);
|
||||
Assert.True(result.RequiresSignature);
|
||||
Assert.Equal(failureReason, result.FailureReason);
|
||||
Assert.True(result.HasVersionAttribute);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
using StellaOps.Plugin.Hosting;
|
||||
|
||||
namespace StellaOps.Plugin.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Unit tests for PluginHostOptions configuration.
|
||||
/// </summary>
|
||||
public sealed class PluginHostOptionsTests
|
||||
{
|
||||
#region Default Values Tests
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void DefaultValues_AreCorrect()
|
||||
{
|
||||
// Arrange & Act
|
||||
var options = new PluginHostOptions();
|
||||
|
||||
// Assert
|
||||
Assert.True(options.EnsureDirectoryExists);
|
||||
Assert.True(options.RecursiveSearch); // Default is true
|
||||
Assert.False(options.EnforceSignatureVerification);
|
||||
Assert.True(options.RequireVersionAttribute); // Default is true
|
||||
Assert.True(options.EnforceVersionCompatibility); // Default is true
|
||||
Assert.True(options.StrictMajorVersionCheck); // Default is true
|
||||
Assert.Null(options.HostVersion);
|
||||
Assert.Null(options.SignatureVerifier);
|
||||
Assert.Empty(options.SearchPatterns);
|
||||
Assert.Empty(options.PluginOrder);
|
||||
Assert.Empty(options.AdditionalPrefixes);
|
||||
Assert.Null(options.BaseDirectory);
|
||||
Assert.Null(options.PluginsDirectory);
|
||||
Assert.Null(options.PrimaryPrefix);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Search Pattern Tests
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void SearchPatterns_CanBeAdded()
|
||||
{
|
||||
// Arrange
|
||||
var options = new PluginHostOptions();
|
||||
|
||||
// Act
|
||||
options.SearchPatterns.Add("MyPrefix.Plugin.*.dll");
|
||||
options.SearchPatterns.Add("Another.Plugin.*.dll");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, options.SearchPatterns.Count);
|
||||
Assert.Contains("MyPrefix.Plugin.*.dll", options.SearchPatterns);
|
||||
Assert.Contains("Another.Plugin.*.dll", options.SearchPatterns);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Plugin Order Tests
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void PluginOrder_CanBeConfigured()
|
||||
{
|
||||
// Arrange
|
||||
var options = new PluginHostOptions();
|
||||
|
||||
// Act
|
||||
options.PluginOrder.Add("PluginA");
|
||||
options.PluginOrder.Add("PluginB");
|
||||
options.PluginOrder.Add("PluginC");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(3, options.PluginOrder.Count);
|
||||
Assert.Equal("PluginA", options.PluginOrder[0]);
|
||||
Assert.Equal("PluginB", options.PluginOrder[1]);
|
||||
Assert.Equal("PluginC", options.PluginOrder[2]);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region BaseDirectory Resolution Tests
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void ResolveBaseDirectory_WhenNull_ReturnsAppContextBaseDirectory()
|
||||
{
|
||||
// Arrange
|
||||
var options = new PluginHostOptions
|
||||
{
|
||||
BaseDirectory = null
|
||||
};
|
||||
|
||||
// Act
|
||||
var resolved = options.ResolveBaseDirectory();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(AppContext.BaseDirectory, resolved);
|
||||
}
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void ResolveBaseDirectory_WhenSet_ReturnsConfiguredValue()
|
||||
{
|
||||
// Arrange
|
||||
var customDir = Path.GetTempPath();
|
||||
var options = new PluginHostOptions
|
||||
{
|
||||
BaseDirectory = customDir
|
||||
};
|
||||
|
||||
// Act
|
||||
var resolved = options.ResolveBaseDirectory();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(customDir, resolved);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Version Configuration Tests
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void HostVersion_CanBeConfigured()
|
||||
{
|
||||
// Arrange
|
||||
var options = new PluginHostOptions();
|
||||
|
||||
// Act
|
||||
options.HostVersion = new Version(2, 1, 0);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(options.HostVersion);
|
||||
Assert.Equal(2, options.HostVersion.Major);
|
||||
Assert.Equal(1, options.HostVersion.Minor);
|
||||
Assert.Equal(0, options.HostVersion.Build);
|
||||
}
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void VersionCompatibility_CanBeEnforced()
|
||||
{
|
||||
// Arrange
|
||||
var options = new PluginHostOptions();
|
||||
|
||||
// Act
|
||||
options.HostVersion = new Version(1, 0, 0);
|
||||
options.RequireVersionAttribute = true;
|
||||
options.EnforceVersionCompatibility = true;
|
||||
options.StrictMajorVersionCheck = true;
|
||||
|
||||
// Assert
|
||||
Assert.True(options.RequireVersionAttribute);
|
||||
Assert.True(options.EnforceVersionCompatibility);
|
||||
Assert.True(options.StrictMajorVersionCheck);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Prefix Configuration Tests
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void PrimaryPrefix_AffectsDefaultDirectory()
|
||||
{
|
||||
// Arrange
|
||||
var options = new PluginHostOptions
|
||||
{
|
||||
PrimaryPrefix = "MyModule"
|
||||
};
|
||||
|
||||
// Assert
|
||||
Assert.Equal("MyModule", options.PrimaryPrefix);
|
||||
}
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void AdditionalPrefixes_CanBeConfigured()
|
||||
{
|
||||
// Arrange
|
||||
var options = new PluginHostOptions();
|
||||
|
||||
// Act
|
||||
options.AdditionalPrefixes.Add("Prefix1");
|
||||
options.AdditionalPrefixes.Add("Prefix2");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, options.AdditionalPrefixes.Count);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Signature Verification Tests
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void SignatureVerification_CanBeEnforced()
|
||||
{
|
||||
// Arrange
|
||||
var options = new PluginHostOptions();
|
||||
|
||||
// Act
|
||||
options.EnforceSignatureVerification = true;
|
||||
|
||||
// Assert
|
||||
Assert.True(options.EnforceSignatureVerification);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Recursive Search Tests
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void RecursiveSearch_CanBeEnabled()
|
||||
{
|
||||
// Arrange
|
||||
var options = new PluginHostOptions();
|
||||
|
||||
// Act
|
||||
options.RecursiveSearch = true;
|
||||
|
||||
// Assert
|
||||
Assert.True(options.RecursiveSearch);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using StellaOps.Plugin.Hosting;
|
||||
using StellaOps.Plugin.Versioning;
|
||||
|
||||
namespace StellaOps.Plugin.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Integration tests for PluginHost plugin loading.
|
||||
/// </summary>
|
||||
public sealed class PluginHostTests
|
||||
{
|
||||
#region LoadPlugins Directory Tests
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void LoadPlugins_NonExistentDirectory_ReturnsEmptyResult()
|
||||
{
|
||||
// Arrange
|
||||
var options = new PluginHostOptions
|
||||
{
|
||||
PluginsDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString(), "plugins"),
|
||||
EnsureDirectoryExists = false
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = PluginHost.LoadPlugins(options);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result.Plugins);
|
||||
Assert.Empty(result.Failures);
|
||||
}
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void LoadPlugins_EmptyDirectory_ReturnsEmptyResult()
|
||||
{
|
||||
// Arrange
|
||||
var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempDir);
|
||||
|
||||
try
|
||||
{
|
||||
var options = new PluginHostOptions
|
||||
{
|
||||
PluginsDirectory = tempDir,
|
||||
EnsureDirectoryExists = false
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = PluginHost.LoadPlugins(options);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result.Plugins);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Directory.Delete(tempDir, true);
|
||||
}
|
||||
}
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void LoadPlugins_EnsureDirectoryExists_CreatesDirectory()
|
||||
{
|
||||
// Arrange
|
||||
var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString(), "plugins");
|
||||
Assert.False(Directory.Exists(tempDir));
|
||||
|
||||
try
|
||||
{
|
||||
var options = new PluginHostOptions
|
||||
{
|
||||
PluginsDirectory = tempDir,
|
||||
EnsureDirectoryExists = true
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = PluginHost.LoadPlugins(options);
|
||||
|
||||
// Assert
|
||||
Assert.True(Directory.Exists(tempDir));
|
||||
Assert.Empty(result.Plugins);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (Directory.Exists(tempDir))
|
||||
{
|
||||
Directory.Delete(tempDir, true);
|
||||
}
|
||||
|
||||
var parent = Path.GetDirectoryName(tempDir);
|
||||
if (parent is not null && Directory.Exists(parent))
|
||||
{
|
||||
Directory.Delete(parent, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void LoadPlugins_NullOptions_ThrowsException()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentNullException>(() => PluginHost.LoadPlugins(null!));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Search Pattern Tests
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void LoadPlugins_CustomSearchPattern_RespectsPattern()
|
||||
{
|
||||
// Arrange
|
||||
var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempDir);
|
||||
|
||||
try
|
||||
{
|
||||
// Create a file that won't match the pattern
|
||||
File.WriteAllText(Path.Combine(tempDir, "NotAPlugin.dll"), "dummy");
|
||||
|
||||
var options = new PluginHostOptions
|
||||
{
|
||||
PluginsDirectory = tempDir,
|
||||
EnsureDirectoryExists = false
|
||||
};
|
||||
options.SearchPatterns.Add("MyPrefix.Plugin.*.dll");
|
||||
|
||||
// Act
|
||||
var result = PluginHost.LoadPlugins(options);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result.Plugins);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Directory.Delete(tempDir, true);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Plugin Order Tests
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public void LoadPlugins_WithPluginOrder_AcceptsOrderConfiguration()
|
||||
{
|
||||
// Arrange
|
||||
var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempDir);
|
||||
|
||||
try
|
||||
{
|
||||
var options = new PluginHostOptions
|
||||
{
|
||||
PluginsDirectory = tempDir,
|
||||
EnsureDirectoryExists = false
|
||||
};
|
||||
options.PluginOrder.Add("PluginA");
|
||||
options.PluginOrder.Add("PluginB");
|
||||
|
||||
// Act
|
||||
var result = PluginHost.LoadPlugins(options);
|
||||
|
||||
// Assert - In an empty directory, no plugins are loaded
|
||||
Assert.Empty(result.Plugins);
|
||||
Assert.NotNull(result.MissingOrderedPlugins);
|
||||
// MissingOrderedPlugins only tracks plugins that were in PluginOrder but not found in discovered files
|
||||
// In an empty directory, no files are discovered, so the list may be empty
|
||||
}
|
||||
finally
|
||||
{
|
||||
Directory.Delete(tempDir, true);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Async Tests
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public async Task LoadPluginsAsync_NonExistentDirectory_ReturnsEmptyResult()
|
||||
{
|
||||
// Arrange
|
||||
var options = new PluginHostOptions
|
||||
{
|
||||
PluginsDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString(), "plugins"),
|
||||
EnsureDirectoryExists = false
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = await PluginHost.LoadPluginsAsync(options);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result.Plugins);
|
||||
Assert.Empty(result.Failures);
|
||||
}
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public async Task LoadPluginsAsync_WithCancellationToken_AcceptsToken()
|
||||
{
|
||||
// Arrange
|
||||
var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempDir);
|
||||
|
||||
try
|
||||
{
|
||||
var options = new PluginHostOptions
|
||||
{
|
||||
PluginsDirectory = tempDir,
|
||||
EnsureDirectoryExists = false
|
||||
};
|
||||
|
||||
using var cts = new CancellationTokenSource();
|
||||
// Don't cancel - just verify the async method accepts a cancellation token
|
||||
|
||||
// Act
|
||||
var result = await PluginHost.LoadPluginsAsync(options, cancellationToken: cts.Token);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result.Plugins);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Directory.Delete(tempDir, true);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -4,19 +4,25 @@
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<UseConcelierTestInfra>false</UseConcelierTestInfra>
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../StellaOps.DependencyInjection/StellaOps.DependencyInjection.csproj" />
|
||||
<ProjectReference Include="../../StellaOps.Plugin/StellaOps.Plugin.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.14.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="10.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" >
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" >
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user