Path: blob/main/extensions/copilot/src/extension/linkify/test/vscode-node/notebookCellLinkifier.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 { suite, test } from 'vitest';6import type { NotebookCell, NotebookDocument, TextDocument } from 'vscode';7import { ILogger, ILogService } from '../../../../platform/log/common/logService';8import { TestWorkspaceService } from '../../../../platform/test/node/testWorkspaceService';9import { IWorkspaceService } from '../../../../platform/workspace/common/workspaceService';10import { CancellationToken } from '../../../../util/vs/base/common/cancellation';11import { StringSHA1 } from '../../../../util/vs/base/common/hash';12import { NotebookCellKind, Uri } from '../../../../vscodeTypes';13import { LinkifiedPart, LinkifyLocationAnchor } from '../../common/linkifiedText';14import { NotebookCellLinkifier } from '../../vscode-node/notebookCellLinkifier';15import { assertPartsEqual } from '../node/util';1617suite('Notebook Cell Linkifier', () => {1819// The cell ID prefix from helpers.ts20const CELL_ID_PREFIX = '#VSC-';2122function createMockNotebookCell(uri: Uri, index: number): NotebookCell {23return {24index,25kind: NotebookCellKind.Code,26document: {27uri,28lineCount: 1,29lineAt: () => ({ text: 'print("hello")' }),30languageId: 'python'31} as unknown as TextDocument,32metadata: {},33outputs: [],34executionSummary: undefined35} as unknown as NotebookCell;36}3738function createMockNotebookDocument(cells: NotebookCell[]): NotebookDocument {39return {40uri: Uri.file('/test/notebook.ipynb'),41getCells: () => cells,42cellCount: cells.length,43cellAt: (index: number) => cells[index],44notebookType: 'jupyter-notebook',45isDirty: false,46isUntitled: false,47isClosed: false,48metadata: {},49version: 1,50save: () => Promise.resolve(true)51} as NotebookDocument;52}5354function createMockWorkspaceService(notebooks: NotebookDocument[]): IWorkspaceService {55return new TestWorkspaceService([], [], notebooks);56}5758function generateCellId(cellUri: Uri): string {59const hash = new StringSHA1();60hash.update(cellUri.toString());61return `${CELL_ID_PREFIX}${hash.digest().substring(0, 8)}`;62}6364const logger: ILogger = {65error: () => { /* no-op */ },66warn: () => { /* no-op */ },67info: () => { /* no-op */ },68debug: () => { /* no-op */ },69trace: () => { /* no-op */ },70show: () => { /* no-op */ },71createSubLogger(): ILogger { return logger; },72withExtraTarget(): ILogger { return logger; }73};74const mockLogger = new class implements ILogService {75_serviceBrand: undefined;76internal = logger;77logger = logger;78trace = logger.trace;79debug = logger.debug;80info = logger.info;81warn = logger.warn;82error = logger.error;83show(preserveFocus?: boolean): void {84//85}86createSubLogger(): ILogger {87return this;88}89withExtraTarget(): ILogger {90return this;91}92}();9394function normalizeParts(parts: readonly LinkifiedPart[]): LinkifiedPart[] {95const normalized: LinkifiedPart[] = [];96for (const part of parts) {97if (typeof part === 'string' && normalized.length && typeof normalized[normalized.length - 1] === 'string') {98normalized[normalized.length - 1] += part; // Concatenate strings99} else {100normalized.push(part);101}102}103return normalized;104}105test('Should linkify actual cell IDs', async () => {106// Create mock cells with specific URIs107const cellUri1 = Uri.parse('vscode-notebook-cell:/test/notebook.ipynb#cell1');108const cellUri2 = Uri.parse('vscode-notebook-cell:/test/notebook.ipynb#cell2');109110const cell1 = createMockNotebookCell(cellUri1, 0);111const cell2 = createMockNotebookCell(cellUri2, 1);112113const notebook = createMockNotebookDocument([cell1, cell2]);114const workspaceService = createMockWorkspaceService([notebook]);115116// Generate the expected cell IDs117const cellId1 = generateCellId(cellUri1);118const cellId2 = generateCellId(cellUri2);119120const linkifier = new NotebookCellLinkifier(workspaceService, mockLogger);121122const testText = `Below is a list of the cells that were executed\n* Cell Id ${cellId1}\n* Cell Id ${cellId2}\n Cell 1: code cell, id=${cellId1}, nor markdown, language=Python\n Cell 2(${cellId2}), nor markdown, language=Python`;123124const result = await linkifier.linkify(testText, { requestId: undefined, references: [] }, CancellationToken.None);125126// Should have linkified both cell IDs127assertPartsEqual(128normalizeParts(result.parts),129[130`Below is a list of the cells that were executed\n* Cell Id ${cellId1} `,131new LinkifyLocationAnchor(cellUri1, 'Cell 1'),132`\n* Cell Id ${cellId2} `,133new LinkifyLocationAnchor(cellUri2, 'Cell 2'),134`\n Cell 1: code cell, id=#VSC-c6b3ce64 `,135new LinkifyLocationAnchor(cellUri1, 'Cell 1'),136`, nor markdown, language=Python\n Cell 2(#VSC-f9c1928a `,137new LinkifyLocationAnchor(cellUri2, 'Cell 2'),138`), nor markdown, language=Python`139]140);141});142});143144145