Use package-lock.json to pin conformance test dependencies (#1247)

This commit is contained in:
Stephen Halter 2026-02-05 17:42:41 -08:00 • committed by GitHub
commit e55ae7b7bd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 1416 additions and 54 deletions

View file

@ -9,19 +9,19 @@ namespace ModelContextProtocol.ConformanceTests;
/// This test runs the Node.js-based conformance test suite for the client
/// and reports the results.
/// </summary>
public class ClientConformanceTests //: IAsyncLifetime
public class ClientConformanceTests
{
private readonly ITestOutputHelper _output;
// Public static property required for SkipUnless attribute
public static bool IsNpxInstalled => NodeHelpers.IsNpxInstalled();
public static bool IsNodeInstalled => NodeHelpers.IsNodeInstalled();
public ClientConformanceTests(ITestOutputHelper output)
{
_output = output;
}
[Theory(Skip = "npx is not installed. Skipping client conformance tests.", SkipUnless = nameof(IsNpxInstalled))]
[Theory(Skip = "Node.js is not installed. Skipping client conformance tests.", SkipUnless = nameof(IsNodeInstalled))]
[InlineData("initialize")]
[InlineData("tools_call")]
[InlineData("auth/metadata-default")]
@ -59,7 +59,7 @@ public class ClientConformanceTests //: IAsyncLifetime
$"ConformanceClient executable not found at: {conformanceClientPath}");
}
var startInfo = NodeHelpers.NpxStartInfo($"-y @modelcontextprotocol/conformance client --scenario {scenario} --command \"{conformanceClientPath} {scenario}\"");
var startInfo = NodeHelpers.ConformanceTestStartInfo($"client --scenario {scenario} --command \"{conformanceClientPath} {scenario}\"");
var outputBuilder = new StringBuilder();
var errorBuilder = new StringBuilder();

View file

@ -52,13 +52,6 @@
<PackageReference Include="System.Linq.AsyncEnumerable" />
</ItemGroup>
<ItemGroup>
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
<_Parameter1>McpConformanceVersion</_Parameter1>
<_Parameter2>$(McpConformanceVersion)</_Parameter2>
</AssemblyAttribute>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\samples\TestServerWithHosting\TestServerWithHosting.csproj" />
<ProjectReference Include="..\..\src\ModelContextProtocol.Core\ModelContextProtocol.Core.csproj" />

View file

@ -97,11 +97,10 @@ public class ServerConformanceTests : IAsyncLifetime
[Fact]
public async Task RunConformanceTests()
{
// Check if Node.js is installed
Assert.SkipWhen(!NodeHelpers.IsNpxInstalled(), "Node.js is not installed. Skipping conformance tests.");
Assert.SkipWhen(!NodeHelpers.IsNodeInstalled(), "Node.js is not installed. Skipping conformance tests.");
// Run the conformance test suite
var result = await RunNpxConformanceTests();
var result = await RunConformanceTestsAsync();
// Report the results
Assert.True(result.Success,
@ -115,21 +114,9 @@ public class ServerConformanceTests : IAsyncLifetime
_serverTask = Task.Run(() => ConformanceServer.Program.MainAsync(["--urls", _serverUrl], new XunitLoggerProvider(_output), cancellationToken: _serverCts.Token));
}
private static string GetConformanceVersion()
private async Task<(bool Success, string Output, string Error)> RunConformanceTestsAsync()
{
var assembly = typeof(ServerConformanceTests).Assembly;
var attribute = assembly.GetCustomAttributes(typeof(System.Reflection.AssemblyMetadataAttribute), false)
.Cast<System.Reflection.AssemblyMetadataAttribute>()
.FirstOrDefault(a => a.Key == "McpConformanceVersion");
return attribute?.Value ?? throw new InvalidOperationException("McpConformanceVersion not found in assembly metadata");
}
private async Task<(bool Success, string Output, string Error)> RunNpxConformanceTests()
{
// Version is configured in Directory.Packages.props for central management
var version = GetConformanceVersion();
var startInfo = NodeHelpers.NpxStartInfo($"-y @modelcontextprotocol/conformance@{version} server --url {_serverUrl}");
var startInfo = NodeHelpers.ConformanceTestStartInfo($"server --url {_serverUrl}");
var outputBuilder = new StringBuilder();
var errorBuilder = new StringBuilder();