Path: blob/main/extensions/copilot/src/extension/mcp/test/vscode-node/nuget.integration.spec.ts
13405 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import path from 'path';6import { beforeEach, describe, expect, it } from 'vitest';7import { ILogService } from '../../../../platform/log/common/logService';8import { IFetcherService } from '../../../../platform/networking/common/fetcherService';9import { ITestingServicesAccessor, TestingServiceCollection } from '../../../../platform/test/node/services';10import { createExtensionUnitTestingServices } from '../../../test/node/services';11import { IMcpStdioServerConfiguration, NuGetMcpSetup } from '../../vscode-node/nuget';12import { CommandExecutor, ICommandExecutor } from '../../vscode-node/util';13import { FixtureFetcherService } from './util';1415const RUN_DOTNET_CLI_TESTS = !!process.env['CI'] && !process.env['BUILD_ARTIFACTSTAGINGDIRECTORY'];1617describe.runIf(RUN_DOTNET_CLI_TESTS).skip('get nuget MCP server info using dotnet CLI', { timeout: 30_000 }, () => {18let testingServiceCollection: TestingServiceCollection;19let accessor: ITestingServicesAccessor;20let logService: ILogService;21let fetcherService: IFetcherService;22let commandExecutor: ICommandExecutor;23let nuget: NuGetMcpSetup;2425beforeEach(() => {26testingServiceCollection = createExtensionUnitTestingServices();27accessor = testingServiceCollection.createTestingAccessor();28logService = accessor.get(ILogService);29fetcherService = new FixtureFetcherService();30commandExecutor = new CommandExecutor();31nuget = new NuGetMcpSetup(32logService,33fetcherService,34commandExecutor,35{ command: 'dotnet', args: [] }, // allow dotnet command to be overridden for testing36path.join(__dirname, 'fixtures', 'nuget') // file based package source for testing37);38});3940it('returns mapped server.json for original schema', async () => {41const result = await nuget.getNuGetPackageMetadata('Knapcode.SampleMcpServer');42expect(result.state).toBe('ok');43if (result.state === 'ok') {44expect(result.getMcpServer).toBeDefined();45if (result.getMcpServer) {46const mcpServer = await result.getMcpServer(Promise.resolve());47expect(mcpServer).toBeDefined();48const config = mcpServer!.config as Omit<IMcpStdioServerConfiguration, 'type'>;49expect(config.command).toBe('dnx');50expect(config.env).toEqual({ 'WEATHER_CHOICES': '${input:weather_choices}' });51expect(config.args).toEqual(['[email protected]', '--yes', '--', 'mcp', 'start']);52} else {53expect.fail();54}55} else {56expect.fail();57}58});5960it('returns mapped server.json for 2025-09-29 schema', async () => {61const result = await nuget.getNuGetPackageMetadata('BaseTestPackage.McpServer');62expect(result.state).toBe('ok');63if (result.state === 'ok') {64expect(result.getMcpServer).toBeDefined();65if (result.getMcpServer) {66const mcpServer = await result.getMcpServer(Promise.resolve());67expect(mcpServer).toBeDefined();68const config = mcpServer!.config as Omit<IMcpStdioServerConfiguration, 'type'>;69expect(config.command).toBe('dnx');70expect(config.env).toEqual({ 'WEATHER_CHOICES': '${input:weather_choices}' });71expect(config.args).toEqual(['[email protected]', '--yes', '--', 'mcp', 'start']);72} else {73expect.fail();74}75} else {76expect.fail();77}78});7980it('returns package metadata', async () => {81const result = await nuget.getNuGetPackageMetadata('basetestpackage.dotnettool');82expect(result.state).toBe('ok');83if (result.state === 'ok') {84expect(result.name).toBe('BaseTestPackage.DotnetTool');85expect(result.version).toBe('1.0.0');86} else {87expect.fail();88}89});9091it('handles missing package', async () => {92const result = await nuget.getNuGetPackageMetadata('BaseTestPackage.DoesNotExist');93expect(result.state).toBe('error');94if (result.state === 'error') {95expect(result.error).toBeDefined();96expect(result.errorType).toBe('NotFound');97} else {98expect.fail();99}100});101102it('handles missing dotnet', async () => {103nuget.dotnet.command = 'dotnet-missing';104const result = await nuget.getNuGetPackageMetadata('Knapcode.SampleMcpServer');105expect(result.state).toBe('error');106if (result.state === 'error') {107expect(result.errorType).toBe('MissingCommand');108expect(result.helpUriLabel).toBe('Install .NET SDK');109expect(result.helpUri).toBe('https://aka.ms/vscode-mcp-install/dotnet');110} else {111expect.fail();112}113});114115it('handles old dotnet version', async () => {116nuget.dotnet.command = 'node';117nuget.dotnet.args = ['-e', 'console.log("9.0.0")', '--'];118const result = await nuget.getNuGetPackageMetadata('Knapcode.SampleMcpServer');119expect(result.state).toBe('error');120if (result.state === 'error') {121expect(result.errorType).toBe('BadCommandVersion');122expect(result.helpUriLabel).toBe('Update .NET SDK');123expect(result.helpUri).toBe('https://aka.ms/vscode-mcp-install/dotnet');124} else {125expect.fail();126}127});128});129130131