diff --git a/src/test/datascience/notebook/intellisense/completion.vscode.common.test.ts b/src/test/datascience/notebook/intellisense/completion.vscode.common.test.ts new file mode 100644 index 000000000000..87624f52b05d --- /dev/null +++ b/src/test/datascience/notebook/intellisense/completion.vscode.common.test.ts @@ -0,0 +1,85 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +/* eslint-disable @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */ +import { assert } from 'chai'; +import * as sinon from 'sinon'; +import { commands, CompletionList, Position, window } from 'vscode'; +import { traceInfo } from '../../../../platform/logging'; +import { IDisposable } from '../../../../platform/common/types'; +import { + closeNotebooksAndCleanUpAfterTests, + runCell, + insertCodeCell, + waitForExecutionCompletedSuccessfully, + prewarmNotebooks, + createEmptyPythonNotebook +} from '../helper'; +import { captureScreenShot, initialize, startJupyterServer } from '../../../common'; +import { getTextOutputValue } from '../../../../kernels/execution/helpers'; + +/* eslint-disable @typescript-eslint/no-explicit-any, no-invalid-this */ +suite('VSCode Intellisense Notebook and Interactive Code Completion @lsp', function () { + const disposables: IDisposable[] = []; + this.timeout(120_000); + suiteSetup(async function () { + traceInfo(`Start Suite Code Completion via Jupyter`); + this.timeout(120_000); + await initialize(); + await startJupyterServer(); + await prewarmNotebooks(); + sinon.restore(); + traceInfo(`Start Suite (Completed) Code Completion via Jupyter`); + }); + // Use same notebook without starting kernel in every single test (use one for whole suite). + setup(async function () { + traceInfo(`Start Test ${this.currentTest?.title}`); + sinon.restore(); + await startJupyterServer(); + await createEmptyPythonNotebook(disposables); + traceInfo(`Start Test (completed) ${this.currentTest?.title}`); + }); + teardown(async function () { + traceInfo(`Ended Test ${this.currentTest?.title}`); + if (this.currentTest?.isFailed()) { + await captureScreenShot(this); + } + await closeNotebooksAndCleanUpAfterTests(disposables); + traceInfo(`Ended Test (completed) ${this.currentTest?.title}`); + }); + suiteTeardown(() => closeNotebooksAndCleanUpAfterTests(disposables)); + test('Execute cell and get completions for variable', async () => { + await insertCodeCell('import sys\nprint(sys.executable)\na = 1', { index: 0 }); + const cell = window.activeNotebookEditor?.notebook.cellAt(0)!; + + await runCell(cell); + + // Wait till execution count changes and status is success. + await waitForExecutionCompletedSuccessfully(cell); + const outputText = getTextOutputValue(cell.outputs[0]).trim(); + traceInfo(`Cell Output ${outputText}`); + await insertCodeCell('a.', { index: 1 }); + const cell2 = window.activeNotebookEditor!.notebook.cellAt(1); + + const position = new Position(0, 2); + traceInfo('Get completions in test'); + // Executing the command `vscode.executeCompletionItemProvider` to simulate triggering completion + const completions = (await commands.executeCommand( + 'vscode.executeCompletionItemProvider', + cell2.document.uri, + position + )) as CompletionList; + const items = completions.items.map((item) => item.label); + assert.isOk(items.length); + assert.ok( + items.find((item) => + typeof item === 'string' ? item.includes('bit_length') : item.label.includes('bit_length') + ) + ); + assert.ok( + items.find((item) => + typeof item === 'string' ? item.includes('to_bytes') : item.label.includes('to_bytes') + ) + ); + }); +}); diff --git a/src/test/datascience/notebook/intellisense/completion.vscode.test.ts b/src/test/datascience/notebook/intellisense/completion.vscode.test.ts index bb9fc9103216..5eb4a8306c2d 100644 --- a/src/test/datascience/notebook/intellisense/completion.vscode.test.ts +++ b/src/test/datascience/notebook/intellisense/completion.vscode.test.ts @@ -1,87 +1,85 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -/* eslint-disable @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */ -import { assert } from 'chai'; -import * as sinon from 'sinon'; -import { commands, CompletionList, Position, window } from 'vscode'; -import { traceInfo } from '../../../../platform/logging'; -import { IDisposable } from '../../../../platform/common/types'; -import { captureScreenShot } from '../../../common.node'; -import { initialize } from '../../../initialize.node'; -import { - closeNotebooksAndCleanUpAfterTests, - runCell, - insertCodeCell, - startJupyterServer, - waitForExecutionCompletedSuccessfully, - prewarmNotebooks, - createEmptyPythonNotebook -} from '../helper.node'; -import { getTextOutputValue } from '../../../../kernels/execution/helpers'; +// /* eslint-disable @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */ +// import { assert } from 'chai'; +// import * as sinon from 'sinon'; +// import { commands, CompletionList, Position, window } from 'vscode'; +// import { traceInfo } from '../../../../platform/logging'; +// import { IDisposable } from '../../../../platform/common/types'; +// import { +// closeNotebooksAndCleanUpAfterTests, +// runCell, +// insertCodeCell, +// waitForExecutionCompletedSuccessfully, +// prewarmNotebooks, +// createEmptyPythonNotebook +// } from '../helper'; +// import { captureScreenShot, initialize, startJupyterServer } from '../../../common'; +// import { getTextOutputValue } from '../../../../kernels/execution/helpers'; -/* eslint-disable @typescript-eslint/no-explicit-any, no-invalid-this */ -suite('VSCode Intellisense Notebook and Interactive Code Completion @lsp', function () { - const disposables: IDisposable[] = []; - this.timeout(120_000); - suiteSetup(async function () { - traceInfo(`Start Suite Code Completion via Jupyter`); - this.timeout(120_000); - await initialize(); - await startJupyterServer(); - await prewarmNotebooks(); - sinon.restore(); - traceInfo(`Start Suite (Completed) Code Completion via Jupyter`); - }); - // Use same notebook without starting kernel in every single test (use one for whole suite). - setup(async function () { - traceInfo(`Start Test ${this.currentTest?.title}`); - sinon.restore(); - await startJupyterServer(); - await createEmptyPythonNotebook(disposables); - traceInfo(`Start Test (completed) ${this.currentTest?.title}`); - }); - teardown(async function () { - traceInfo(`Ended Test ${this.currentTest?.title}`); - if (this.currentTest?.isFailed()) { - await captureScreenShot(this); - } - await closeNotebooksAndCleanUpAfterTests(disposables); - traceInfo(`Ended Test (completed) ${this.currentTest?.title}`); - }); - suiteTeardown(() => closeNotebooksAndCleanUpAfterTests(disposables)); - test('Execute cell and get completions for variable', async () => { - await insertCodeCell('import sys\nprint(sys.executable)\na = 1', { index: 0 }); - const cell = window.activeNotebookEditor?.notebook.cellAt(0)!; +// /* eslint-disable @typescript-eslint/no-explicit-any, no-invalid-this */ +// suite('VSCode Intellisense Notebook and Interactive Code Completion @lsp', function () { +// const disposables: IDisposable[] = []; +// this.timeout(120_000); +// suiteSetup(async function () { +// traceInfo(`Start Suite Code Completion via Jupyter`); +// this.timeout(120_000); +// await initialize(); +// await startJupyterServer(); +// await prewarmNotebooks(); +// sinon.restore(); +// traceInfo(`Start Suite (Completed) Code Completion via Jupyter`); +// }); +// // Use same notebook without starting kernel in every single test (use one for whole suite). +// setup(async function () { +// traceInfo(`Start Test ${this.currentTest?.title}`); +// sinon.restore(); +// await startJupyterServer(); +// await createEmptyPythonNotebook(disposables); +// traceInfo(`Start Test (completed) ${this.currentTest?.title}`); +// }); +// teardown(async function () { +// traceInfo(`Ended Test ${this.currentTest?.title}`); +// if (this.currentTest?.isFailed()) { +// await captureScreenShot(this); +// } +// await closeNotebooksAndCleanUpAfterTests(disposables); +// traceInfo(`Ended Test (completed) ${this.currentTest?.title}`); +// }); +// suiteTeardown(() => closeNotebooksAndCleanUpAfterTests(disposables)); +// test('Execute cell and get completions for variable', async () => { +// await insertCodeCell('import sys\nprint(sys.executable)\na = 1', { index: 0 }); +// const cell = window.activeNotebookEditor?.notebook.cellAt(0)!; - await runCell(cell); +// await runCell(cell); - // Wait till execution count changes and status is success. - await waitForExecutionCompletedSuccessfully(cell); - const outputText = getTextOutputValue(cell.outputs[0]).trim(); - traceInfo(`Cell Output ${outputText}`); - await insertCodeCell('a.', { index: 1 }); - const cell2 = window.activeNotebookEditor!.notebook.cellAt(1); +// // Wait till execution count changes and status is success. +// await waitForExecutionCompletedSuccessfully(cell); +// const outputText = getTextOutputValue(cell.outputs[0]).trim(); +// traceInfo(`Cell Output ${outputText}`); +// await insertCodeCell('a.', { index: 1 }); +// const cell2 = window.activeNotebookEditor!.notebook.cellAt(1); - const position = new Position(0, 2); - traceInfo('Get completions in test'); - // Executing the command `vscode.executeCompletionItemProvider` to simulate triggering completion - const completions = (await commands.executeCommand( - 'vscode.executeCompletionItemProvider', - cell2.document.uri, - position - )) as CompletionList; - const items = completions.items.map((item) => item.label); - assert.isOk(items.length); - assert.ok( - items.find((item) => - typeof item === 'string' ? item.includes('bit_length') : item.label.includes('bit_length') - ) - ); - assert.ok( - items.find((item) => - typeof item === 'string' ? item.includes('to_bytes') : item.label.includes('to_bytes') - ) - ); - }); -}); +// const position = new Position(0, 2); +// traceInfo('Get completions in test'); +// // Executing the command `vscode.executeCompletionItemProvider` to simulate triggering completion +// const completions = (await commands.executeCommand( +// 'vscode.executeCompletionItemProvider', +// cell2.document.uri, +// position +// )) as CompletionList; +// const items = completions.items.map((item) => item.label); +// assert.isOk(items.length); +// assert.ok( +// items.find((item) => +// typeof item === 'string' ? item.includes('bit_length') : item.label.includes('bit_length') +// ) +// ); +// assert.ok( +// items.find((item) => +// typeof item === 'string' ? item.includes('to_bytes') : item.label.includes('to_bytes') +// ) +// ); +// }); +// }); diff --git a/src/test/datascience/notebook/intellisense/completionProvider.vscode.common.test.ts b/src/test/datascience/notebook/intellisense/completionProvider.vscode.common.test.ts new file mode 100644 index 000000000000..8f87439a1b57 --- /dev/null +++ b/src/test/datascience/notebook/intellisense/completionProvider.vscode.common.test.ts @@ -0,0 +1,213 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +/* eslint-disable @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */ +import { assert } from 'chai'; +import * as path from '../../../../platform/vscode-path/path'; +import * as sinon from 'sinon'; +import { ConfigurationTarget, Position, window, workspace, WorkspaceConfiguration, WorkspaceEdit } from 'vscode'; +import { traceInfo } from '../../../../platform/logging'; +import { IDisposable } from '../../../../platform/common/types'; +import { IS_REMOTE_NATIVE_TEST } from '../../../constants'; +import { + closeNotebooksAndCleanUpAfterTests, + runCell, + insertCodeCell, + waitForExecutionCompletedSuccessfully, + prewarmNotebooks, + createEmptyPythonNotebook, + getCellOutputs, + waitForCompletions +} from '../helper'; +import { IExtensionTestApi, initialize, startJupyterServer } from '../../../common'; +import { KernelCompletionProvider } from '../../../../standalone/intellisense/kernelCompletionProvider'; +import { IKernelProvider } from '../../../../kernels/types'; + +/* eslint-disable @typescript-eslint/no-explicit-any, no-invalid-this */ +[true, false].forEach((useJedi) => { + suite( + `DataScience - VSCode Intellisense Notebook - (Code Completion via Jupyter) ${ + useJedi ? 'withJedi' : 'withoutJedi' + } @lsp`, + function () { + let api: IExtensionTestApi; + const disposables: IDisposable[] = []; + let kernelCompletionProviderRegistry: KernelCompletionProvider; + this.timeout(120_000); + let jupyterConfig: WorkspaceConfiguration; + let previousJediSetting: boolean | undefined; + + suiteSetup(async function () { + if (IS_REMOTE_NATIVE_TEST()) { + return this.skip(); + } + traceInfo(`Start Suite Code Completion via Jupyter`); + this.timeout(120_000); + jupyterConfig = workspace.getConfiguration('jupyter', undefined); + previousJediSetting = jupyterConfig.get('enableExtendedPythonKernelCompletions'); + await jupyterConfig.update( + 'enableExtendedPythonKernelCompletions', + useJedi, + ConfigurationTarget.Global + ); + api = await initialize(); + await startJupyterServer(); + await prewarmNotebooks(); + sinon.restore(); + kernelCompletionProviderRegistry = + api.serviceContainer.get(KernelCompletionProvider); + traceInfo(`Start Suite (Completed) Code Completion via Jupyter`); + }); + // Use same notebook without starting kernel in every single test (use one for whole suite). + setup(async function () { + traceInfo(`Start Test ${this.currentTest?.title}`); + sinon.restore(); + await startJupyterServer(); + await createEmptyPythonNotebook(disposables, undefined, true); + traceInfo(`Start Test (completed) ${this.currentTest?.title}`); + }); + teardown(async function () { + sinon.restore(); + traceInfo(`Ended Test ${this.currentTest?.title}`); + await closeNotebooksAndCleanUpAfterTests(disposables); + traceInfo(`Ended Test (completed) ${this.currentTest?.title}`); + }); + suiteTeardown(async () => { + await jupyterConfig.update( + 'enableExtendedPythonKernelCompletions', + previousJediSetting, + ConfigurationTarget.Global + ); + await closeNotebooksAndCleanUpAfterTests(disposables); + }); + /** + * Test completions. + * @param {string} cellCode e.g. `df.` + * @param {string} itemToExistInCompletion E.g. `Name`, `Age` + * @param {string} textToFilterCompletions The text typed to filter the list, e.g. `N`. + * @param {string} itemToExistInCompletionAfterFilter The filtered list, e.g. if user types `N`, then `Age` will not show up, but `Name` will. + */ + async function testCompletions( + cellCode: string, + triggerCharacter: string | undefined, + itemToNotExistInCompletion?: string, + itemToExistInCompletion?: string, + textToFilterCompletions?: string, + itemToExistInCompletionAfterFilter?: string + ) { + await insertCodeCell( + `import pandas as pd\ndf = pd.DataFrame({'Name': ['Foo', 'Bar', 'Baz'],'Sex': ['Male', 'Female', 'Male'],'Age': [1,2,3]})`, + { + index: 1 + } + ); + const cell = window.activeNotebookEditor?.notebook.cellAt(1)!; + + await runCell(cell); + + // Wait till execution count changes and status is success. + await waitForExecutionCompletedSuccessfully(cell); + const cell2 = await insertCodeCell('import os\nprint(os.getcwd())\n'); + await runCell(cell2); + + // Wait till execution count changes and status is success. + await waitForExecutionCompletedSuccessfully(cell2); + traceInfo(`last cell output: ${getCellOutputs(cell2)}`); + + // Now add the cell to check intellisense. + await insertCodeCell(cellCode); + const cell3 = window.activeNotebookEditor!.notebook.cellAt(3); + // If we're testing string completions, ensure the cursor position is inside the string quotes. + let position = new Position( + 0, + cellCode.includes('"') || cellCode.includes("'") ? cellCode.length - 1 : cellCode.length + ); + traceInfo('Get completions in test'); + const kernel = api.serviceContainer + .get(IKernelProvider) + .get(window.activeNotebookEditor!.notebook)!; + const completionProvider = kernelCompletionProviderRegistry.kernelCompletionProviders.get(kernel)!; + let completions = await waitForCompletions(completionProvider, cell3, position, triggerCharacter); + let items = completions.map((item) => item.label); + assert.isOk(items.length); + if (itemToExistInCompletion) { + assert.ok( + items.find((item) => + typeof item === 'string' + ? item.includes(itemToExistInCompletion) + : item.label.includes(itemToExistInCompletion) + ) + ); + } else { + return; + } + if (itemToNotExistInCompletion) { + assert.isUndefined( + items.find((item) => + typeof item === 'string' + ? item.includes(itemToNotExistInCompletion) + : item.label.includes(itemToNotExistInCompletion) + ) + ); + } + // Make sure it is skipping items that are already provided by pylance (no dupes) + // Pylance isn't returning them right now: https://github.com/microsoft/vscode-jupyter/issues/8842 + // assert.notOk( + // items.find((item) => (typeof item === 'string' ? item.includes('Name') : item.label.includes('Name'))) + // ); + + if (!textToFilterCompletions || !itemToExistInCompletionAfterFilter) { + return; + } + // Add some text after the . and make sure we still get completions + const edit = new WorkspaceEdit(); + edit.insert(cell3.document.uri, new Position(cellCode.length, 0), textToFilterCompletions); + await workspace.applyEdit(edit); + position = new Position(0, cellCode.length + textToFilterCompletions.length); + completions = await waitForCompletions(completionProvider, cell3, position, triggerCharacter); + items = completions.map((item) => item.label); + assert.isOk(items.length); + assert.isUndefined( + // Since we've filtered the completion the old item will no longer exist. + items.find((item) => + typeof item === 'string' + ? item.includes(itemToExistInCompletion) + : item.label.includes(itemToExistInCompletion) + ) + ); + assert.ok( + items.find((item) => + typeof item === 'string' + ? item.includes(itemToExistInCompletionAfterFilter) + : item.label.includes(itemToExistInCompletionAfterFilter) + ) + ); + } + test('Dataframe completions', async () => { + const fileName = path.basename(window.activeNotebookEditor!.notebook.uri.fsPath); + await testCompletions('df.', '.', fileName, 'Age', 'S', 'Sex'); + }); + test.skip('Dataframe column completions', async () => { + // https://github.com/microsoft/vscode-jupyter/issues/14012 + const fileName = path.basename(window.activeNotebookEditor!.notebook.uri.fsPath); + await testCompletions('df.Name.', '.', fileName, 'add_prefix', 'add_s', 'add_suffix'); + }); + test('Dataframe assignment completions', async () => { + const fileName = path.basename(window.activeNotebookEditor!.notebook.uri.fsPath); + await testCompletions('var_name = df.', '.', fileName, 'Age', 'S', 'Sex'); + }); + test('Dataframe assignment column completions', async () => { + const fileName = path.basename(window.activeNotebookEditor!.notebook.uri.fsPath); + await testCompletions(fileName.substring(0, 1), fileName); + }); + test('File path completions with double quotes', async () => { + const fileName = path.basename(window.activeNotebookEditor!.notebook.uri.fsPath); + await testCompletions(`"${fileName.substring(0, 1)}"`, undefined, fileName); + }); + test('File path completions with single quotes', async () => { + const fileName = path.basename(window.activeNotebookEditor!.notebook.uri.fsPath); + await testCompletions(`'${fileName.substring(0, 1)}'`, undefined, fileName); + }); + } + ); +}); diff --git a/src/test/datascience/notebook/intellisense/completionProvider.vscode.test.ts b/src/test/datascience/notebook/intellisense/completionProvider.vscode.test.ts index 642effb8b27d..709b5b439d31 100644 --- a/src/test/datascience/notebook/intellisense/completionProvider.vscode.test.ts +++ b/src/test/datascience/notebook/intellisense/completionProvider.vscode.test.ts @@ -1,217 +1,213 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -/* eslint-disable @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */ -import { assert } from 'chai'; -import * as path from '../../../../platform/vscode-path/path'; -import * as sinon from 'sinon'; -import { ConfigurationTarget, Position, Uri, window, workspace, WorkspaceConfiguration, WorkspaceEdit } from 'vscode'; -import { traceInfo } from '../../../../platform/logging'; -import { IDisposable } from '../../../../platform/common/types'; -import { IExtensionTestApi } from '../../../common.node'; -import { IS_REMOTE_NATIVE_TEST } from '../../../constants.node'; -import { EXTENSION_ROOT_DIR_FOR_TESTS, initialize } from '../../../initialize.node'; -import { - closeNotebooksAndCleanUpAfterTests, - runCell, - insertCodeCell, - startJupyterServer, - waitForExecutionCompletedSuccessfully, - prewarmNotebooks, - createEmptyPythonNotebook, - getCellOutputs, - waitForCompletions -} from '../helper.node'; -import { KernelCompletionProvider } from '../../../../standalone/intellisense/kernelCompletionProvider'; -import { IKernelProvider } from '../../../../kernels/types'; +// /* eslint-disable @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */ +// import { assert } from 'chai'; +// import * as path from '../../../../platform/vscode-path/path'; +// import * as sinon from 'sinon'; +// import { ConfigurationTarget, Position, window, workspace, WorkspaceConfiguration, WorkspaceEdit } from 'vscode'; +// import { traceInfo } from '../../../../platform/logging'; +// import { IDisposable } from '../../../../platform/common/types'; +// import { IS_REMOTE_NATIVE_TEST } from '../../../constants'; +// import { +// closeNotebooksAndCleanUpAfterTests, +// runCell, +// insertCodeCell, +// waitForExecutionCompletedSuccessfully, +// prewarmNotebooks, +// createEmptyPythonNotebook, +// getCellOutputs, +// waitForCompletions +// } from '../helper'; +// import { IExtensionTestApi, initialize, startJupyterServer } from '../../../common'; +// import { KernelCompletionProvider } from '../../../../standalone/intellisense/kernelCompletionProvider'; +// import { IKernelProvider } from '../../../../kernels/types'; -/* eslint-disable @typescript-eslint/no-explicit-any, no-invalid-this */ -[true, false].forEach((useJedi) => { - suite( - `DataScience - VSCode Intellisense Notebook - (Code Completion via Jupyter) ${ - useJedi ? 'withJedi' : 'withoutJedi' - } @lsp`, - function () { - let api: IExtensionTestApi; - const disposables: IDisposable[] = []; - let kernelCompletionProviderRegistry: KernelCompletionProvider; - this.timeout(120_000); - let jupyterConfig: WorkspaceConfiguration; - let previousJediSetting: boolean | undefined; +// /* eslint-disable @typescript-eslint/no-explicit-any, no-invalid-this */ +// [true, false].forEach((useJedi) => { +// suite( +// `DataScience - VSCode Intellisense Notebook - (Code Completion via Jupyter) ${ +// useJedi ? 'withJedi' : 'withoutJedi' +// } @lsp`, +// function () { +// let api: IExtensionTestApi; +// const disposables: IDisposable[] = []; +// let kernelCompletionProviderRegistry: KernelCompletionProvider; +// this.timeout(120_000); +// let jupyterConfig: WorkspaceConfiguration; +// let previousJediSetting: boolean | undefined; - suiteSetup(async function () { - if (IS_REMOTE_NATIVE_TEST()) { - return this.skip(); - } - traceInfo(`Start Suite Code Completion via Jupyter`); - this.timeout(120_000); - jupyterConfig = workspace.getConfiguration('jupyter', undefined); - previousJediSetting = jupyterConfig.get('enableExtendedPythonKernelCompletions'); - await jupyterConfig.update( - 'enableExtendedPythonKernelCompletions', - useJedi, - ConfigurationTarget.Global - ); - api = await initialize(); - await startJupyterServer(); - await prewarmNotebooks(); - sinon.restore(); - kernelCompletionProviderRegistry = - api.serviceContainer.get(KernelCompletionProvider); - traceInfo(`Start Suite (Completed) Code Completion via Jupyter`); - }); - // Use same notebook without starting kernel in every single test (use one for whole suite). - setup(async function () { - traceInfo(`Start Test ${this.currentTest?.title}`); - sinon.restore(); - await startJupyterServer(); - await createEmptyPythonNotebook(disposables, Uri.file(path.join(EXTENSION_ROOT_DIR_FOR_TESTS, 'temp'))); // TODO, can't do this on web tests - traceInfo(`Start Test (completed) ${this.currentTest?.title}`); - }); - teardown(async function () { - sinon.restore(); - traceInfo(`Ended Test ${this.currentTest?.title}`); - await closeNotebooksAndCleanUpAfterTests(disposables); - traceInfo(`Ended Test (completed) ${this.currentTest?.title}`); - }); - suiteTeardown(async () => { - await jupyterConfig.update( - 'enableExtendedPythonKernelCompletions', - previousJediSetting, - ConfigurationTarget.Global - ); - await closeNotebooksAndCleanUpAfterTests(disposables); - }); - /** - * Test completions. - * @param {string} cellCode e.g. `df.` - * @param {string} itemToExistInCompletion E.g. `Name`, `Age` - * @param {string} textToFilterCompletions The text typed to filter the list, e.g. `N`. - * @param {string} itemToExistInCompletionAfterFilter The filtered list, e.g. if user types `N`, then `Age` will not show up, but `Name` will. - */ - async function testCompletions( - cellCode: string, - triggerCharacter: string | undefined, - itemToNotExistInCompletion?: string, - itemToExistInCompletion?: string, - textToFilterCompletions?: string, - itemToExistInCompletionAfterFilter?: string - ) { - await insertCodeCell('%pip install pandas', { - index: 0 - }); - const namesCsvPath = path.join(__dirname, 'names.csv').replace(/\\/g, '/').replace('out', 'src'); +// suiteSetup(async function () { +// if (IS_REMOTE_NATIVE_TEST()) { +// return this.skip(); +// } +// traceInfo(`Start Suite Code Completion via Jupyter`); +// this.timeout(120_000); +// jupyterConfig = workspace.getConfiguration('jupyter', undefined); +// previousJediSetting = jupyterConfig.get('enableExtendedPythonKernelCompletions'); +// await jupyterConfig.update( +// 'enableExtendedPythonKernelCompletions', +// useJedi, +// ConfigurationTarget.Global +// ); +// api = await initialize(); +// await startJupyterServer(); +// await prewarmNotebooks(); +// sinon.restore(); +// kernelCompletionProviderRegistry = +// api.serviceContainer.get(KernelCompletionProvider); +// traceInfo(`Start Suite (Completed) Code Completion via Jupyter`); +// }); +// // Use same notebook without starting kernel in every single test (use one for whole suite). +// setup(async function () { +// traceInfo(`Start Test ${this.currentTest?.title}`); +// sinon.restore(); +// await startJupyterServer(); +// await createEmptyPythonNotebook(disposables, undefined, true); +// traceInfo(`Start Test (completed) ${this.currentTest?.title}`); +// }); +// teardown(async function () { +// sinon.restore(); +// traceInfo(`Ended Test ${this.currentTest?.title}`); +// await closeNotebooksAndCleanUpAfterTests(disposables); +// traceInfo(`Ended Test (completed) ${this.currentTest?.title}`); +// }); +// suiteTeardown(async () => { +// await jupyterConfig.update( +// 'enableExtendedPythonKernelCompletions', +// previousJediSetting, +// ConfigurationTarget.Global +// ); +// await closeNotebooksAndCleanUpAfterTests(disposables); +// }); +// /** +// * Test completions. +// * @param {string} cellCode e.g. `df.` +// * @param {string} itemToExistInCompletion E.g. `Name`, `Age` +// * @param {string} textToFilterCompletions The text typed to filter the list, e.g. `N`. +// * @param {string} itemToExistInCompletionAfterFilter The filtered list, e.g. if user types `N`, then `Age` will not show up, but `Name` will. +// */ +// async function testCompletions( +// cellCode: string, +// triggerCharacter: string | undefined, +// itemToNotExistInCompletion?: string, +// itemToExistInCompletion?: string, +// textToFilterCompletions?: string, +// itemToExistInCompletionAfterFilter?: string +// ) { +// await insertCodeCell( +// `import pandas as pd\ndf = pd.DataFrame({'Name': ['Foo', 'Bar', 'Baz'],'Sex': ['Male', 'Female', 'Male'],'Age': [1,2,3]})`, +// { +// index: 1 +// } +// ); +// const cell = window.activeNotebookEditor?.notebook.cellAt(1)!; - await insertCodeCell(`import pandas as pd\ndf = pd.read_csv("${namesCsvPath}")\n`, { - index: 1 - }); - const cell2 = window.activeNotebookEditor?.notebook.cellAt(1)!; +// await runCell(cell); - await runCell(cell2); +// // Wait till execution count changes and status is success. +// await waitForExecutionCompletedSuccessfully(cell); +// const cell2 = await insertCodeCell('import os\nprint(os.getcwd())\n'); +// await runCell(cell2); - // Wait till execution count changes and status is success. - await waitForExecutionCompletedSuccessfully(cell2); - const cell3 = await insertCodeCell('import os\nprint(os.getcwd())\n'); - await runCell(cell3); +// // Wait till execution count changes and status is success. +// await waitForExecutionCompletedSuccessfully(cell2); +// traceInfo(`last cell output: ${getCellOutputs(cell2)}`); - // Wait till execution count changes and status is success. - await waitForExecutionCompletedSuccessfully(cell3); - traceInfo(`last cell output: ${getCellOutputs(cell3)}`); +// // Now add the cell to check intellisense. +// await insertCodeCell(cellCode); +// const cell3 = window.activeNotebookEditor!.notebook.cellAt(3); +// // If we're testing string completions, ensure the cursor position is inside the string quotes. +// let position = new Position( +// 0, +// cellCode.includes('"') || cellCode.includes("'") ? cellCode.length - 1 : cellCode.length +// ); +// traceInfo('Get completions in test'); +// const kernel = api.serviceContainer +// .get(IKernelProvider) +// .get(window.activeNotebookEditor!.notebook)!; +// const completionProvider = kernelCompletionProviderRegistry.kernelCompletionProviders.get(kernel)!; +// let completions = await waitForCompletions(completionProvider, cell3, position, triggerCharacter); +// let items = completions.map((item) => item.label); +// assert.isOk(items.length); +// if (itemToExistInCompletion) { +// assert.ok( +// items.find((item) => +// typeof item === 'string' +// ? item.includes(itemToExistInCompletion) +// : item.label.includes(itemToExistInCompletion) +// ) +// ); +// } else { +// return; +// } +// if (itemToNotExistInCompletion) { +// assert.isUndefined( +// items.find((item) => +// typeof item === 'string' +// ? item.includes(itemToNotExistInCompletion) +// : item.label.includes(itemToNotExistInCompletion) +// ) +// ); +// } +// // Make sure it is skipping items that are already provided by pylance (no dupes) +// // Pylance isn't returning them right now: https://github.com/microsoft/vscode-jupyter/issues/8842 +// // assert.notOk( +// // items.find((item) => (typeof item === 'string' ? item.includes('Name') : item.label.includes('Name'))) +// // ); - // Now add the cell to check intellisense. - await insertCodeCell(cellCode); - const cell4 = window.activeNotebookEditor!.notebook.cellAt(3); - // If we're testing string completions, ensure the cursor position is inside the string quotes. - let position = new Position( - 0, - cellCode.includes('"') || cellCode.includes("'") ? cellCode.length - 1 : cellCode.length - ); - traceInfo('Get completions in test'); - const kernel = api.serviceContainer - .get(IKernelProvider) - .get(window.activeNotebookEditor!.notebook)!; - const completionProvider = kernelCompletionProviderRegistry.kernelCompletionProviders.get(kernel)!; - let completions = await waitForCompletions(completionProvider, cell4, position, triggerCharacter); - let items = completions.map((item) => item.label); - assert.isOk(items.length); - if (itemToExistInCompletion) { - assert.ok( - items.find((item) => - typeof item === 'string' - ? item.includes(itemToExistInCompletion) - : item.label.includes(itemToExistInCompletion) - ) - ); - } else { - return; - } - if (itemToNotExistInCompletion) { - assert.isUndefined( - items.find((item) => - typeof item === 'string' - ? item.includes(itemToNotExistInCompletion) - : item.label.includes(itemToNotExistInCompletion) - ) - ); - } - // Make sure it is skipping items that are already provided by pylance (no dupes) - // Pylance isn't returning them right now: https://github.com/microsoft/vscode-jupyter/issues/8842 - // assert.notOk( - // items.find((item) => (typeof item === 'string' ? item.includes('Name') : item.label.includes('Name'))) - // ); - - if (!textToFilterCompletions || !itemToExistInCompletionAfterFilter) { - return; - } - // Add some text after the . and make sure we still get completions - const edit = new WorkspaceEdit(); - edit.insert(cell4.document.uri, new Position(cellCode.length, 0), textToFilterCompletions); - await workspace.applyEdit(edit); - position = new Position(0, cellCode.length + textToFilterCompletions.length); - completions = await waitForCompletions(completionProvider, cell4, position, triggerCharacter); - items = completions.map((item) => item.label); - assert.isOk(items.length); - assert.isUndefined( - // Since we've filtered the completion the old item will no longer exist. - items.find((item) => - typeof item === 'string' - ? item.includes(itemToExistInCompletion) - : item.label.includes(itemToExistInCompletion) - ) - ); - assert.ok( - items.find((item) => - typeof item === 'string' - ? item.includes(itemToExistInCompletionAfterFilter) - : item.label.includes(itemToExistInCompletionAfterFilter) - ) - ); - } - test('Dataframe completions', async () => { - const fileName = path.basename(window.activeNotebookEditor!.notebook.uri.fsPath); - await testCompletions('df.', '.', fileName, 'Age', 'S', 'Sex'); - }); - test.skip('Dataframe column completions', async () => { - // https://github.com/microsoft/vscode-jupyter/issues/14012 - const fileName = path.basename(window.activeNotebookEditor!.notebook.uri.fsPath); - await testCompletions('df.Name.', '.', fileName, 'add_prefix', 'add_s', 'add_suffix'); - }); - test('Dataframe assignment completions', async () => { - const fileName = path.basename(window.activeNotebookEditor!.notebook.uri.fsPath); - await testCompletions('var_name = df.', '.', fileName, 'Age', 'S', 'Sex'); - }); - test('Dataframe assignment column completions', async () => { - const fileName = path.basename(window.activeNotebookEditor!.notebook.uri.fsPath); - await testCompletions(fileName.substring(0, 1), fileName); - }); - test('File path completions with double quotes', async () => { - const fileName = path.basename(window.activeNotebookEditor!.notebook.uri.fsPath); - await testCompletions(`"${fileName.substring(0, 1)}"`, undefined, fileName); - }); - test('File path completions with single quotes', async () => { - const fileName = path.basename(window.activeNotebookEditor!.notebook.uri.fsPath); - await testCompletions(`'${fileName.substring(0, 1)}'`, undefined, fileName); - }); - } - ); -}); +// if (!textToFilterCompletions || !itemToExistInCompletionAfterFilter) { +// return; +// } +// // Add some text after the . and make sure we still get completions +// const edit = new WorkspaceEdit(); +// edit.insert(cell3.document.uri, new Position(cellCode.length, 0), textToFilterCompletions); +// await workspace.applyEdit(edit); +// position = new Position(0, cellCode.length + textToFilterCompletions.length); +// completions = await waitForCompletions(completionProvider, cell3, position, triggerCharacter); +// items = completions.map((item) => item.label); +// assert.isOk(items.length); +// assert.isUndefined( +// // Since we've filtered the completion the old item will no longer exist. +// items.find((item) => +// typeof item === 'string' +// ? item.includes(itemToExistInCompletion) +// : item.label.includes(itemToExistInCompletion) +// ) +// ); +// assert.ok( +// items.find((item) => +// typeof item === 'string' +// ? item.includes(itemToExistInCompletionAfterFilter) +// : item.label.includes(itemToExistInCompletionAfterFilter) +// ) +// ); +// } +// test('Dataframe completions', async () => { +// const fileName = path.basename(window.activeNotebookEditor!.notebook.uri.fsPath); +// await testCompletions('df.', '.', fileName, 'Age', 'S', 'Sex'); +// }); +// test.skip('Dataframe column completions', async () => { +// // https://github.com/microsoft/vscode-jupyter/issues/14012 +// const fileName = path.basename(window.activeNotebookEditor!.notebook.uri.fsPath); +// await testCompletions('df.Name.', '.', fileName, 'add_prefix', 'add_s', 'add_suffix'); +// }); +// test('Dataframe assignment completions', async () => { +// const fileName = path.basename(window.activeNotebookEditor!.notebook.uri.fsPath); +// await testCompletions('var_name = df.', '.', fileName, 'Age', 'S', 'Sex'); +// }); +// test('Dataframe assignment column completions', async () => { +// const fileName = path.basename(window.activeNotebookEditor!.notebook.uri.fsPath); +// await testCompletions(fileName.substring(0, 1), fileName); +// }); +// test('File path completions with double quotes', async () => { +// const fileName = path.basename(window.activeNotebookEditor!.notebook.uri.fsPath); +// await testCompletions(`"${fileName.substring(0, 1)}"`, undefined, fileName); +// }); +// test('File path completions with single quotes', async () => { +// const fileName = path.basename(window.activeNotebookEditor!.notebook.uri.fsPath); +// await testCompletions(`'${fileName.substring(0, 1)}'`, undefined, fileName); +// }); +// } +// ); +// });