diff --git a/.vscode/launch.json b/.vscode/launch.json index 272b0790d45f..233420f4e6e6 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -285,7 +285,7 @@ "--ui=tdd", "--recursive", "--colors", - //"--grep", "", + // "--grep", "", "--timeout=300000", "--exit" ], diff --git a/package.nls.json b/package.nls.json index 1ac367aa3c94..9d13ec263652 100644 --- a/package.nls.json +++ b/package.nls.json @@ -561,9 +561,10 @@ "DataScienceRendererExtension.downloadCompletedOutputMessage": "Notebook Renderers extension download complete.", "DataScience.uriProviderDescriptionFormat": "{0} (From {1} extension)", "DataScience.unknownPackage": "unknown", - "DataScience.interactiveWindowTitleFormat": "Python Interactive - {0}", - "DataScience.interactiveWindowModeBannerTitle": "Do you want to open a new Python Interactive window for this file? [More Information](command:workbench.action.openSettings?%5B%22python.dataScience.interactiveWindowMode%22%5D).", - "DataScience.interactiveWindowModeBannerSwitchYes": "Yes", - "DataScience.interactiveWindowModeBannerSwitchAlways": "Always", - "DataScience.interactiveWindowModeBannerSwitchNo": "No" + "DataScience.interactiveWindowTitle" : "Python Interactive", + "DataScience.interactiveWindowTitleFormat" : "Python Interactive - {0}", + "DataScience.interactiveWindowModeBannerTitle" : "Do you want to open a new Python Interactive window for this file? [More Information](command:workbench.action.openSettings?%5B%22python.dataScience.interactiveWindowMode%22%5D).", + "DataScience.interactiveWindowModeBannerSwitchYes" : "Yes", + "DataScience.interactiveWindowModeBannerSwitchAlways" : "Always", + "DataScience.interactiveWindowModeBannerSwitchNo" : "No" } diff --git a/src/client/common/utils/localize.ts b/src/client/common/utils/localize.ts index 5159c64b5636..fef6ce522e05 100644 --- a/src/client/common/utils/localize.ts +++ b/src/client/common/utils/localize.ts @@ -324,7 +324,7 @@ export namespace DataScience { '{0} (From {1} extension)' ); export const unknownPackage = localize('DataScience.unknownPackage', 'unknown'); - export const interactiveWindowTitle = localize('DataScience.interactiveWindowTitleFormat', 'Python Interactive'); + export const interactiveWindowTitle = localize('DataScience.interactiveWindowTitle', 'Python Interactive'); export const interactiveWindowTitleFormat = localize( 'DataScience.interactiveWindowTitleFormat', 'Python Interactive - {0}' diff --git a/src/client/datascience/jupyter/jupyterNotebook.ts b/src/client/datascience/jupyter/jupyterNotebook.ts index f339aa1c57f4..c37690b1a05d 100644 --- a/src/client/datascience/jupyter/jupyterNotebook.ts +++ b/src/client/datascience/jupyter/jupyterNotebook.ts @@ -225,13 +225,19 @@ export class JupyterNotebookBase implements INotebook { this.sessionStatusChanged.dispose(); this.onStatusChangedEvent = undefined; } - - traceInfo(`Shutting down session ${this.identity.toString()}`); - if (this.session) { - await this.session.dispose().catch(traceError.bind('Failed to dispose session from JupyterNotebook')); - } this.loggers.forEach((d) => d.dispose()); this.disposed.fire(); + + try { + traceInfo(`Shutting down session ${this.identity.toString()}`); + if (this.session) { + await this.session + .dispose() + .catch(traceError.bind('Failed to dispose session from JupyterNotebook')); + } + } catch (exc) { + traceError(`Exception shutting down session `, exc); + } } } diff --git a/src/test/datascience/dataScienceIocContainer.ts b/src/test/datascience/dataScienceIocContainer.ts index a98b792be54b..4840870be77f 100644 --- a/src/test/datascience/dataScienceIocContainer.ts +++ b/src/test/datascience/dataScienceIocContainer.ts @@ -9,7 +9,7 @@ import { interfaces } from 'inversify'; import * as os from 'os'; import * as path from 'path'; import { SemVer } from 'semver'; -import { anything, instance, mock, reset, when } from 'ts-mockito'; +import { anyString, anything, instance, mock, reset, when } from 'ts-mockito'; import * as TypeMoq from 'typemoq'; import { CancellationTokenSource, @@ -20,6 +20,7 @@ import { FileSystemWatcher, Memento, Uri, + WindowState, WorkspaceFolder, WorkspaceFoldersChangeEvent } from 'vscode'; @@ -68,6 +69,7 @@ import { IDiagnosticsService } from '../../client/application/diagnostics/types'; import { ApplicationEnvironment } from '../../client/common/application/applicationEnvironment'; +import { ApplicationShell } from '../../client/common/application/applicationShell'; import { ClipboardService } from '../../client/common/application/clipboard'; import { VSCodeNotebook } from '../../client/common/application/notebook'; import { TerminalManager } from '../../client/common/application/terminalManager'; @@ -158,6 +160,7 @@ import { ICryptoUtils, ICurrentProcess, IDataScienceSettings, + IDisposable, IExperimentService, IExperimentsManager, IExtensionContext, @@ -424,7 +427,7 @@ export class DataScienceIocContainer extends UnitTestIocContainer { } private static jupyterInterpreters: PythonInterpreter[] = []; private static foundPythonPath: string | undefined; - public applicationShell!: TypeMoq.IMock; + public applicationShell!: ApplicationShell; // tslint:disable-next-line:no-any public datascience!: TypeMoq.IMock; public shouldMockJupyter: boolean; @@ -938,7 +941,7 @@ export class DataScienceIocContainer extends UnitTestIocContainer { this.serviceManager.addSingletonInstance(ICommandManager, this.commandManager); // Mock the app shell - const appShell = (this.applicationShell = TypeMoq.Mock.ofType()); + this.applicationShell = mock(ApplicationShell); const configurationService = TypeMoq.Mock.ofType(); configurationService.setup((c) => c.getSettings(TypeMoq.It.isAny())).returns(this.getSettings.bind(this)); @@ -948,7 +951,7 @@ export class DataScienceIocContainer extends UnitTestIocContainer { EnvironmentVariablesProvider ); - this.serviceManager.addSingletonInstance(IApplicationShell, appShell.object); + this.serviceManager.addSingletonInstance(IApplicationShell, instance(this.applicationShell)); this.serviceManager.addSingleton(IClipboard, ClipboardService); this.serviceManager.addSingletonInstance(IDocumentManager, this.documentManager); this.serviceManager.addSingletonInstance( @@ -1131,35 +1134,52 @@ export class DataScienceIocContainer extends UnitTestIocContainer { } }; - appShell.setup((a) => a.showErrorMessage(TypeMoq.It.isAnyString())).returns(() => Promise.resolve('')); - appShell - .setup((a) => a.showErrorMessage(TypeMoq.It.isAnyString(), anything())) - .returns(() => Promise.resolve('')); - appShell - .setup((a) => a.showErrorMessage(TypeMoq.It.isAnyString(), anything(), anything())) - .returns(() => Promise.resolve('')); - appShell - .setup((a) => a.showInformationMessage(TypeMoq.It.isAny(), TypeMoq.It.isAny())) - .returns(() => Promise.resolve('')); - appShell - .setup((a) => a.showInformationMessage(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())) - .returns((_a1: string, a2: string, _a3: string) => Promise.resolve(a2)); - appShell - .setup((a) => - a.showInformationMessage(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()) - ) - .returns((_a1: string, a2: any, _a3: string, a4: string) => { + when(this.applicationShell.showErrorMessage(anyString())).thenReturn(Promise.resolve('')); + when(this.applicationShell.showErrorMessage(anyString(), anything())).thenReturn(Promise.resolve('')); + when(this.applicationShell.showErrorMessage(anyString(), anything(), anything())).thenReturn( + Promise.resolve('') + ); + when(this.applicationShell.showInformationMessage(anyString())).thenReturn(Promise.resolve('')); + when(this.applicationShell.showInformationMessage(anyString(), anything())).thenReturn(Promise.resolve('')); + when( + this.applicationShell.showInformationMessage(anyString(), anything(), anything()) + ).thenCall((_a1, a2, _a3) => Promise.resolve(a2)); + when(this.applicationShell.showInformationMessage(anyString(), anything(), anything(), anything())).thenCall( + (_a1, a2, _a3, a4) => { if (typeof a2 === 'string') { return Promise.resolve(a2); } else { return Promise.resolve(a4); } - }); - appShell - .setup((a) => a.showSaveDialog(TypeMoq.It.isAny())) - .returns(() => Promise.resolve(Uri.file('test.ipynb'))); - appShell.setup((a) => a.setStatusBarMessage(TypeMoq.It.isAny())).returns(() => dummyDisposable); - appShell.setup((a) => a.showInputBox(TypeMoq.It.isAny())).returns(() => Promise.resolve('Python')); + } + ); + when(this.applicationShell.showWarningMessage(anyString())).thenReturn(Promise.resolve('')); + when(this.applicationShell.showWarningMessage(anyString(), anything())).thenReturn(Promise.resolve('')); + when(this.applicationShell.showWarningMessage(anyString(), anything(), anything())).thenCall((_a1, a2, _a3) => + Promise.resolve(a2) + ); + when(this.applicationShell.showWarningMessage(anyString(), anything(), anything(), anything())).thenCall( + (_a1, a2, _a3, a4) => { + if (typeof a2 === 'string') { + return Promise.resolve(a2); + } else { + return Promise.resolve(a4); + } + } + ); + when(this.applicationShell.showSaveDialog(anything())).thenReturn(Promise.resolve(Uri.file('test.ipynb'))); + when(this.applicationShell.setStatusBarMessage(anything())).thenReturn(dummyDisposable); + when(this.applicationShell.showInputBox(anything())).thenReturn(Promise.resolve('Python')); + const eventCallback = ( + _listener: (e: WindowState) => any, + _thisArgs?: any, + _disposables?: IDisposable[] | Disposable + ) => { + return { + dispose: noop + }; + }; + when(this.applicationShell.onDidChangeWindowState).thenReturn(eventCallback); const interpreterManager = this.serviceContainer.get(IInterpreterService); interpreterManager.initialize(); diff --git a/src/test/datascience/interactiveWindow.functional.test.tsx b/src/test/datascience/interactiveWindow.functional.test.tsx index 9faf7ca2a0ec..aeafe1d2b455 100644 --- a/src/test/datascience/interactiveWindow.functional.test.tsx +++ b/src/test/datascience/interactiveWindow.functional.test.tsx @@ -709,6 +709,8 @@ for i in range(0, 100): ); // Then open a second time and make sure it uses this new path + const secondPath = await interpreterService.getActiveInterpreter(secondUri); + assert.notEqual(secondPath?.path, activeInterpreter?.path, 'Second path was not set'); const newWindow = (await interactiveWindowProvider.getOrCreate(undefined)) as InteractiveWindow; await addCode(ioc, 'a=1\na', false, secondUri); assert.notEqual( @@ -1237,12 +1239,12 @@ for i in range(0, 100): const lenses = fooWatcher?.getCodeLenses(); assert.equal(lenses?.length, 6, 'No code lenses found'); await runCodeLens(fooWatcher!.uri!, lenses ? lenses[0] : undefined, ioc); - verifyHtmlOnCell(pair1.mount.wrapper, 'InteractiveCell', 'foo', CellPosition.Last); + verifyHtmlOnCell(pair1.mount.wrapper, 'InteractiveCell', 'foo', CellPosition.Last); // Create another window, run a cell again const pair2 = await getOrCreateInteractiveWindow(ioc); await runCodeLens(fooWatcher!.uri!, lenses ? lenses[0] : undefined, ioc); - verifyHtmlOnCell(pair2.mount.wrapper, 'InteractiveCell', 'foo', CellPosition.Last); + verifyHtmlOnCell(pair2.mount.wrapper, 'InteractiveCell', 'foo', CellPosition.Last); // Make the first window active pair2.mount.changeViewState(false, false); @@ -1253,7 +1255,7 @@ for i in range(0, 100): const lenses2 = barWatcher?.getCodeLenses(); assert.equal(lenses2?.length, 6, 'No code lenses found'); await runCodeLens(barWatcher!.uri!, lenses2 ? lenses2[0] : undefined, ioc); - verifyHtmlOnCell(pair1.mount.wrapper, 'InteractiveCell', 'bar', CellPosition.Last); + verifyHtmlOnCell(pair1.mount.wrapper, 'InteractiveCell', 'bar', CellPosition.Last); }); test('Per file', async () => { addMockData(ioc, fooCode, 'foo'); @@ -1268,7 +1270,7 @@ for i in range(0, 100): await runCodeLens(fooWatcher!.uri!, lenses ? lenses[0] : undefined, ioc); assert.equal(interactiveWindowProvider.windows.length, 1, 'Interactive window not created'); const mounted1 = interactiveWindowProvider.getMountedWebView(interactiveWindowProvider.windows[0]); - verifyHtmlOnCell(mounted1.wrapper, 'InteractiveCell', 'foo', CellPosition.Last); + verifyHtmlOnCell(mounted1.wrapper, 'InteractiveCell', 'foo', CellPosition.Last); // Create another window, run a cell again const barWatcher = createCodeWatcher(`# %%\n${barCode}`, 'bar.py', ioc); @@ -1278,16 +1280,11 @@ for i in range(0, 100): const mounted2 = interactiveWindowProvider.getMountedWebView( interactiveWindowProvider.windows.find((w) => w.title.includes('bar')) ); - verifyHtmlOnCell(mounted2.wrapper, 'InteractiveCell', 'bar', CellPosition.Last); + verifyHtmlOnCell(mounted2.wrapper, 'InteractiveCell', 'bar', CellPosition.Last); }); test('Per file asks and changes titles', async () => { addMockData(ioc, fooCode, 'foo'); addMockData(ioc, barCode, 'bar'); - ioc.applicationShell - .setup((i) => i.showInformationMessage(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())) - .returns((_a1: string, a2: string, _a3: string) => { - return Promise.resolve(a2); - }); ioc.forceDataScienceSettingsChanged({ interactiveWindowMode: 'multiple' }); const interactiveWindowProvider = ioc.get(IInteractiveWindowProvider); const globalMemento = ioc.get(IMemento, GLOBAL_MEMENTO); @@ -1300,7 +1297,7 @@ for i in range(0, 100): await runCodeLens(fooWatcher!.uri!, lenses ? lenses[0] : undefined, ioc); assert.equal(interactiveWindowProvider.windows.length, 1, 'Interactive window not created'); const mounted1 = interactiveWindowProvider.getMountedWebView(interactiveWindowProvider.windows[0]); - verifyHtmlOnCell(mounted1.wrapper, 'InteractiveCell', 'foo', CellPosition.Last); + verifyHtmlOnCell(mounted1.wrapper, 'InteractiveCell', 'foo', CellPosition.Last); // Create another window, run a cell again const barWatcher = createCodeWatcher(`# %%\n${barCode}`, 'bar.py', ioc); @@ -1310,7 +1307,7 @@ for i in range(0, 100): const mounted2 = interactiveWindowProvider.getMountedWebView( interactiveWindowProvider.windows.find((w) => w.title.includes('bar')) ); - verifyHtmlOnCell(mounted2.wrapper, 'InteractiveCell', 'bar', CellPosition.Last); + verifyHtmlOnCell(mounted2.wrapper, 'InteractiveCell', 'bar', CellPosition.Last); // First window should now have foo in the title too assert.ok(interactiveWindowProvider.windows[0].title.includes('foo'), 'Title of first window did not change'); diff --git a/src/test/datascience/nativeEditor.functional.test.tsx b/src/test/datascience/nativeEditor.functional.test.tsx index ee1e50a96505..9427ee73fd92 100644 --- a/src/test/datascience/nativeEditor.functional.test.tsx +++ b/src/test/datascience/nativeEditor.functional.test.tsx @@ -7,6 +7,7 @@ import * as chaiAsPromised from 'chai-as-promised'; import * as dedent from 'dedent'; import { ReactWrapper } from 'enzyme'; import * as fs from 'fs-extra'; +import { IDisposable } from 'monaco-editor'; import * as path from 'path'; import * as sinon from 'sinon'; import { anything, objectContaining, when } from 'ts-mockito'; @@ -903,7 +904,9 @@ df.head()`; await promise; } } - await ioc.dispose(); + if (ioc) { + await ioc.dispose(); + } try { notebookFile.cleanupCallback(); } catch { @@ -2074,11 +2077,19 @@ df.head()`; } await initIoc(); + const eventCallback = ( + listener: (e: WindowState) => any, + _thisArgs?: any, + _disposables?: IDisposable[] | Disposable + ) => { + windowStateChangeHandlers.push(listener); + return { + dispose: noop + }; + }; windowStateChangeHandlers = []; // Keep track of all handlers for the onDidChangeWindowState event. - ioc.applicationShell - .setup((app) => app.onDidChangeWindowState(TypeMoq.It.isAny())) - .callback((cb) => windowStateChangeHandlers.push(cb)); + when(ioc.applicationShell.onDidChangeWindowState).thenReturn(eventCallback); // tslint:disable-next-line: no-invalid-this await setupFunction.call(this); diff --git a/src/test/datascience/notebook.functional.test.ts b/src/test/datascience/notebook.functional.test.ts index 820f5eedbe16..10ebaeb65bab 100644 --- a/src/test/datascience/notebook.functional.test.ts +++ b/src/test/datascience/notebook.functional.test.ts @@ -11,7 +11,6 @@ import * as path from 'path'; import { SemVer } from 'semver'; import { Readable, Writable } from 'stream'; import { anything, instance, mock, when } from 'ts-mockito'; -import * as TypeMoq from 'typemoq'; import * as uuid from 'uuid/v4'; import { Disposable, Uri } from 'vscode'; import { CancellationToken, CancellationTokenSource } from 'vscode-jsonrpc'; @@ -275,14 +274,9 @@ suite('DataScience notebook tests', () => { function runTest( name: string, func: (_this: Mocha.Context) => Promise, - _notebookProc?: ChildProcess, - rebindFunc?: () => void + _notebookProc?: ChildProcess ) { test(name, async function () { - // Give tests a chance to rebind IOC services before we fetch jupyterExecution and processFactory - if (rebindFunc) { - rebindFunc(); - } console.log(`Starting test ${name} ...`); // tslint:disable-next-line: no-invalid-this return func(this); @@ -489,57 +483,19 @@ suite('DataScience notebook tests', () => { } } }, - undefined, - () => { - const dummyDisposable = { - dispose: () => { - return; - } - }; - const appShell = TypeMoq.Mock.ofType(); - appShell - .setup((a) => a.showErrorMessage(TypeMoq.It.isAnyString())) - .returns((e) => { - throw e; - }); - appShell - .setup((a) => a.showInformationMessage(TypeMoq.It.isAny(), TypeMoq.It.isAny())) - .returns(() => Promise.resolve('')); - appShell - .setup((a) => - a.showInformationMessage(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()) - ) - .returns((_a1: string, a2: string, _a3: string) => Promise.resolve(a2)); - appShell - .setup((a) => - a.showInformationMessage( - TypeMoq.It.isAny(), - TypeMoq.It.isAny(), - TypeMoq.It.isAny(), - TypeMoq.It.isAny() - ) - ) - .returns((_a1: string, a2: string, _a3: string, _a4: string) => Promise.resolve(a2)); - appShell - .setup((a) => - a.showWarningMessage( - TypeMoq.It.isAny(), - TypeMoq.It.isAny(), - TypeMoq.It.isAny(), - TypeMoq.It.isAny() - ) - ) - .returns((_a1: string, a2: string, _a3: string, _a4: string) => Promise.resolve(a2)); - appShell.setup((a) => a.showInputBox(TypeMoq.It.isAny())).returns(() => Promise.resolve('')); - appShell.setup((a) => a.setStatusBarMessage(TypeMoq.It.isAny())).returns(() => dummyDisposable); - ioc.serviceManager.rebindInstance(IApplicationShell, appShell.object); - } + undefined ); // For a connection to a remote machine that is not secure deny the connection and we should not connect runTest( 'Remote Deny Insecure', async () => { + when( + ioc.applicationShell.showWarningMessage(anything(), anything(), anything(), anything()) + ).thenCall((_a1, _a2, a3, _a4) => { + return Promise.resolve(a3); + }); + const pythonService = await createPythonService(); if (pythonService) { @@ -559,55 +515,17 @@ suite('DataScience notebook tests', () => { ]); // Try to create, we expect a failure here as we will deny the insecure connection - await createNotebook(uri, undefined, true); + let madeItPast = false; + try { + await createNotebook(uri, undefined); + madeItPast = true; + } catch (exc) { + assert.ok(exc.toString().includes('insecure'), `Invalid exception thrown: ${exc}`); + } + assert.notOk(madeItPast, 'Should have thrown an exception'); } }, - undefined, - () => { - const dummyDisposable = { - dispose: () => { - return; - } - }; - const appShell = TypeMoq.Mock.ofType(); - appShell - .setup((a) => a.showErrorMessage(TypeMoq.It.isAnyString())) - .returns((e) => { - throw e; - }); - appShell - .setup((a) => a.showInformationMessage(TypeMoq.It.isAny(), TypeMoq.It.isAny())) - .returns(() => Promise.resolve('')); - appShell - .setup((a) => - a.showInformationMessage(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()) - ) - .returns((_a1: string, a2: string, _a3: string) => Promise.resolve(a2)); - appShell - .setup((a) => - a.showInformationMessage( - TypeMoq.It.isAny(), - TypeMoq.It.isAny(), - TypeMoq.It.isAny(), - TypeMoq.It.isAny() - ) - ) - .returns((_a1: string, a2: string, _a3: string, _a4: string) => Promise.resolve(a2)); - // This is the call to app shell that we are changing from the above test - appShell - .setup((a) => - a.showWarningMessage( - TypeMoq.It.isAny(), - TypeMoq.It.isAny(), - TypeMoq.It.isAny(), - TypeMoq.It.isAny() - ) - ) - .returns((_a1: string, _a2: string, a3: string, _a4: string) => Promise.resolve(a3)); - appShell.setup((a) => a.showInputBox(TypeMoq.It.isAny())).returns(() => Promise.resolve('')); - appShell.setup((a) => a.setStatusBarMessage(TypeMoq.It.isAny())).returns(() => dummyDisposable); - ioc.serviceManager.rebindInstance(IApplicationShell, appShell.object); - } + undefined ); runTest('Remote Password', async () => { const pythonService = await createPythonService(); diff --git a/src/test/datascience/testInteractiveWindowProvider.ts b/src/test/datascience/testInteractiveWindowProvider.ts index eeec630aecf0..7b9d6489014d 100644 --- a/src/test/datascience/testInteractiveWindowProvider.ts +++ b/src/test/datascience/testInteractiveWindowProvider.ts @@ -59,7 +59,7 @@ export class TestInteractiveWindowProvider extends InteractiveWindowProvider imp } public getMountedWebView(window: IInteractiveWindow | undefined): IMountedWebView { - const key = window ? window.identity.toString() : this.windows[0].identity.toString(); + const key = window ? window.identity.toString() : this.windows[0]?.identity.toString(); if (!this.windowToMountMap.has(key)) { throw new Error('Test Failure: Window not mounted yet.'); } diff --git a/src/test/datascience/uiTests/notebookUi.ts b/src/test/datascience/uiTests/notebookUi.ts index 4ae6d2d3d6f0..e6f686ac6dbe 100644 --- a/src/test/datascience/uiTests/notebookUi.ts +++ b/src/test/datascience/uiTests/notebookUi.ts @@ -5,6 +5,7 @@ import { assert } from 'chai'; import { ElementHandle } from 'playwright-chromium'; +import { sleep } from '../../../client/common/utils/async'; import { InteractiveWindowMessages } from '../../../client/datascience/interactive-common/interactiveWindowTypes'; import { INotebookEditor } from '../../../client/datascience/types'; import { BaseWebUI } from './helpers'; @@ -37,8 +38,13 @@ export class NotebookEditorUI extends BaseWebUI { // Make sure to wait for idle so that the button is clickable. await this.waitForIdle(); + // Wait just a bit longer to make sure button is visible (not sure why it isn't clicking the button sometimes) + await sleep(500); + // Click the run button. const runButton = await this.getToolbarButton(cellIndex, CellToolbarButton.run); + // tslint:disable-next-line: no-console + console.log(`Executing cell ${cellIndex} by clicking ${runButton.toString()}`); await Promise.all([runButton.click({ button: 'left', force: true, timeout: 0 }), renderedPromise]); } diff --git a/src/test/initialize.ts b/src/test/initialize.ts index 606fefa7682e..6f19dbc4a8d1 100644 --- a/src/test/initialize.ts +++ b/src/test/initialize.ts @@ -107,7 +107,7 @@ function isANotebookOpen() { // tslint:disable if ( Array.isArray((vscode as any).notebook.visibleNotebookEditors) && - vscode.notebook.visibleNotebookEditors.length + (vscode as any).notebook.visibleNotebookEditors.length ) { return true; }