Path: blob/main/extensions/copilot/src/extension/mcp/test/vscode-node/util.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 * as fs from 'fs/promises';6import path from 'path';7import { FetchOptions, IAbortController, IFetcherService, PaginationOptions, Response, WebSocketConnection } from '../../../../platform/networking/common/fetcherService';8import { CancellationToken } from '../../../../util/vs/base/common/cancellation';9import { Event } from '../../../../util/vs/base/common/event';10import { ICommandExecutor } from '../../vscode-node/util';1112type CommandResult = { fileName?: string; stdout?: string; exitCode: number };1314export class FixtureCommandExecutor implements ICommandExecutor {15commands: Array<{ command: string; args: string[]; cwd: string }> = [];1617constructor(public readonly fullCommandToResultMap: Map<string, CommandResult> = new Map()) { }1819async executeWithTimeout(command: string, args: string[], cwd: string, timeoutMs?: number, expectZeroExitCode?: boolean, cancellationToken?: CancellationToken): Promise<{ stdout: string; stderr: string; exitCode: number }> {20this.commands.push({ command, args, cwd });2122let stdout: string = '';23let exitCode: number = 1;24if (this.fullCommandToResultMap) {25const fullCommand = `${command} ${args.join(' ')}`;26const result = this.fullCommandToResultMap.get(fullCommand);27if (result) {28exitCode = result.exitCode;29if (result.fileName) {30const filePath = path.join(__dirname, 'fixtures', 'snapshots', result.fileName);31stdout = await fs.readFile(filePath, 'utf-8');32} else if (result.stdout) {33stdout = result.stdout;34}35}36}3738if (expectZeroExitCode && exitCode !== 0) {39return Promise.reject(new Error(`Expected zero exit code but got ${exitCode}`));40}4142return Promise.resolve({43exitCode,44stdout,45stderr: '',46});47}48}4950export class FixtureFetcherService implements IFetcherService {51urls: Array<string> = [];5253constructor(readonly urlToFileNameMap: Map<string, { fileName: string; status: number }> = new Map()) { }5455async fetch(url: string, options: FetchOptions): Promise<Response> {56this.urls.push(url);5758const result = this.urlToFileNameMap?.get(url);59if (!result) {60return Promise.resolve({61ok: false,62status: 404,63json: async () => ({ message: 'Not Found' }),64} as Response);65} else {66const filePath = path.join(__dirname, 'fixtures', 'snapshots', result.fileName);67const content = await fs.readFile(filePath, 'utf-8');68return Promise.resolve({69ok: result.status === 200,70status: result.status,71text: async () => content,72json: async () => JSON.parse(content),73} as Response);74}75}7677async fetchWithPagination<T>(baseUrl: string, options: PaginationOptions<T>): Promise<T[]> {78const items: T[] = [];79const pageSize = options.pageSize ?? 20;80let page = options.startPage ?? 1;81let hasNextPage = false;8283do {84const url = options.buildUrl(baseUrl, pageSize, page);85const response = await this.fetch(url, options);8687if (!response.ok) {88// Return what we've collected so far if request fails89return items;90}9192const data = await response.json();93const pageItems = options.getItemsFromResponse(data);94items.push(...pageItems);9596hasNextPage = pageItems.length === pageSize;97page++;98} while (hasNextPage);99100return items;101}102103_serviceBrand: undefined;104readonly onDidFetch = Event.None;105readonly onDidCompleteFetch = Event.None;106getUserAgentLibrary(): string { throw new Error('Method not implemented.'); }107createWebSocket(_url: string): WebSocketConnection { throw new Error('Method not implemented.'); }108disconnectAll(): Promise<unknown> { throw new Error('Method not implemented.'); }109makeAbortController(): IAbortController { throw new Error('Method not implemented.'); }110isAbortError(e: any): boolean { throw new Error('Method not implemented.'); }111isInternetDisconnectedError(e: any): boolean { throw new Error('Method not implemented.'); }112isFetcherError(e: any): boolean { throw new Error('Method not implemented.'); }113isNetworkProcessCrashedError(e: any): boolean { throw new Error('Method not implemented.'); }114getUserMessageForFetcherError(err: any): string { throw new Error('Method not implemented.'); }115}116117118