From 41935fd6bb5fff0cb4d498500ff0e6b963a6b1f9 Mon Sep 17 00:00:00 2001 From: rchiodo Date: Wed, 22 Jul 2020 11:00:49 -0700 Subject: [PATCH 1/7] A bunch of fixes for nightly tests --- .../datascience/jupyter/jupyterNotebook.ts | 16 +++++++++++----- src/test/datascience/dataScienceIocContainer.ts | 17 +++++++++++++++++ .../interactiveWindow.functional.test.tsx | 14 +++++++------- src/test/datascience/uiTests/notebookUi.ts | 6 ++++++ src/test/initialize.ts | 2 +- 5 files changed, 42 insertions(+), 13 deletions(-) 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..ef911ca9b5af 100644 --- a/src/test/datascience/dataScienceIocContainer.ts +++ b/src/test/datascience/dataScienceIocContainer.ts @@ -1155,6 +1155,23 @@ export class DataScienceIocContainer extends UnitTestIocContainer { return Promise.resolve(a4); } }); + appShell + .setup((a) => a.showWarningMessage(TypeMoq.It.isAny(), TypeMoq.It.isAny())) + .returns(() => Promise.resolve('')); + appShell + .setup((a) => a.showWarningMessage(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())) + .returns((_a1: string, a2: string, _a3: 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: any, _a3: string, a4: string) => { + 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'))); diff --git a/src/test/datascience/interactiveWindow.functional.test.tsx b/src/test/datascience/interactiveWindow.functional.test.tsx index 9faf7ca2a0ec..25999587145f 100644 --- a/src/test/datascience/interactiveWindow.functional.test.tsx +++ b/src/test/datascience/interactiveWindow.functional.test.tsx @@ -1237,12 +1237,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 +1253,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 +1268,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,7 +1278,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); }); test('Per file asks and changes titles', async () => { addMockData(ioc, fooCode, 'foo'); @@ -1300,7 +1300,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 +1310,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/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; } From 7a7aa398cd6b3f66fc64afeacf4d8a66112a75d9 Mon Sep 17 00:00:00 2001 From: rchiodo Date: Wed, 22 Jul 2020 11:24:58 -0700 Subject: [PATCH 2/7] Fix python interactive title --- .vscode/launch.json | 4 ++-- package.nls.json | 1 + src/client/common/utils/localize.ts | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 272b0790d45f..0f6cc1cbc350 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -285,7 +285,7 @@ "--ui=tdd", "--recursive", "--colors", - //"--grep", "", + "--grep", "Multiple Interpreters", "--timeout=300000", "--exit" ], @@ -293,7 +293,7 @@ // Remove `X` prefix to test with real browser to host DS ui (for DS functional tests). "XVSC_PYTHON_DS_UI_BROWSER": "1", // Remove `X` prefix to test with real python (for DS functional tests). - "XVSCODE_PYTHON_ROLLING": "1", + "VSCODE_PYTHON_ROLLING": "1", // Remove 'X' to turn on all logging in the debug output "XVSC_PYTHON_FORCE_LOGGING": "1", // Remove `X` prefix and update path to test with real python interpreter (for DS functional tests). diff --git a/package.nls.json b/package.nls.json index f4963ea49b25..6a05df579449 100644 --- a/package.nls.json +++ b/package.nls.json @@ -560,6 +560,7 @@ "DataScienceRendererExtension.downloadCompletedOutputMessage": "Notebook Renderers extension download complete.", "DataScience.uriProviderDescriptionFormat": "{0} (From {1} extension)", "DataScience.unknownPackage": "unknown", + "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", diff --git a/src/client/common/utils/localize.ts b/src/client/common/utils/localize.ts index b22c61576890..df1d1e304ff4 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}' From f54cb7f0bb8553c29d4121a237a66b5388c14a29 Mon Sep 17 00:00:00 2001 From: rchiodo Date: Wed, 22 Jul 2020 13:19:52 -0700 Subject: [PATCH 3/7] Rework container to support rewiring appshell --- .vscode/launch.json | 4 +- .../datascience/dataScienceIocContainer.ts | 67 ++++------- .../interactiveWindow.functional.test.tsx | 5 - .../nativeEditor.functional.test.tsx | 19 +++- .../datascience/notebook.functional.test.ts | 107 ++---------------- 5 files changed, 48 insertions(+), 154 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 0f6cc1cbc350..233420f4e6e6 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -285,7 +285,7 @@ "--ui=tdd", "--recursive", "--colors", - "--grep", "Multiple Interpreters", + // "--grep", "", "--timeout=300000", "--exit" ], @@ -293,7 +293,7 @@ // Remove `X` prefix to test with real browser to host DS ui (for DS functional tests). "XVSC_PYTHON_DS_UI_BROWSER": "1", // Remove `X` prefix to test with real python (for DS functional tests). - "VSCODE_PYTHON_ROLLING": "1", + "XVSCODE_PYTHON_ROLLING": "1", // Remove 'X' to turn on all logging in the debug output "XVSC_PYTHON_FORCE_LOGGING": "1", // Remove `X` prefix and update path to test with real python interpreter (for DS functional tests). diff --git a/src/test/datascience/dataScienceIocContainer.ts b/src/test/datascience/dataScienceIocContainer.ts index ef911ca9b5af..d330c40ae87f 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, @@ -68,6 +68,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'; @@ -424,7 +425,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 +939,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 +949,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,52 +1132,28 @@ 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.showWarningMessage(TypeMoq.It.isAny(), TypeMoq.It.isAny())) - .returns(() => Promise.resolve('')); - appShell - .setup((a) => a.showWarningMessage(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())) - .returns((_a1: string, a2: string, _a3: 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: any, _a3: string, a4: string) => { - 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.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 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 25999587145f..1c90ec71dc1c 100644 --- a/src/test/datascience/interactiveWindow.functional.test.tsx +++ b/src/test/datascience/interactiveWindow.functional.test.tsx @@ -1283,11 +1283,6 @@ for i in range(0, 100): 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); 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..d6fc6a7f9932 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) { @@ -562,52 +518,7 @@ suite('DataScience notebook tests', () => { await createNotebook(uri, undefined, true); } }, - 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(); From b025ef65b70ceffb2a789abcf678ccb3385f698d Mon Sep 17 00:00:00 2001 From: rchiodo Date: Wed, 22 Jul 2020 13:26:31 -0700 Subject: [PATCH 4/7] Broke other remote tests, forgot warning overload. --- src/test/datascience/dataScienceIocContainer.ts | 14 ++++++++++++++ src/test/datascience/notebook.functional.test.ts | 9 ++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/test/datascience/dataScienceIocContainer.ts b/src/test/datascience/dataScienceIocContainer.ts index d330c40ae87f..4140b4d216e0 100644 --- a/src/test/datascience/dataScienceIocContainer.ts +++ b/src/test/datascience/dataScienceIocContainer.ts @@ -1151,6 +1151,20 @@ export class DataScienceIocContainer extends UnitTestIocContainer { } } ); + 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')); diff --git a/src/test/datascience/notebook.functional.test.ts b/src/test/datascience/notebook.functional.test.ts index d6fc6a7f9932..10ebaeb65bab 100644 --- a/src/test/datascience/notebook.functional.test.ts +++ b/src/test/datascience/notebook.functional.test.ts @@ -515,7 +515,14 @@ 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 From a25e0460eb15bc0658f2ffb138560814e29d5531 Mon Sep 17 00:00:00 2001 From: rchiodo Date: Wed, 22 Jul 2020 14:08:48 -0700 Subject: [PATCH 5/7] Some more fixups and hope for multiple --- src/test/datascience/interactiveWindow.functional.test.tsx | 2 ++ src/test/datascience/testInteractiveWindowProvider.ts | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/datascience/interactiveWindow.functional.test.tsx b/src/test/datascience/interactiveWindow.functional.test.tsx index 1c90ec71dc1c..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( 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.'); } From 7394c15cbd59b80015a7cbd9679eb5bfbef71583 Mon Sep 17 00:00:00 2001 From: rchiodo Date: Wed, 22 Jul 2020 15:01:56 -0700 Subject: [PATCH 6/7] Missing other app shell method --- src/test/datascience/dataScienceIocContainer.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/test/datascience/dataScienceIocContainer.ts b/src/test/datascience/dataScienceIocContainer.ts index 4140b4d216e0..28c4bf9cbc07 100644 --- a/src/test/datascience/dataScienceIocContainer.ts +++ b/src/test/datascience/dataScienceIocContainer.ts @@ -27,6 +27,7 @@ import * as vsls from 'vsls/vscode'; import { KernelDaemonPool } from '../../client/datascience/kernel-launcher/kernelDaemonPool'; import { promisify } from 'util'; +import { WindowState } from 'vscode'; import { LanguageServerExtensionActivationService } from '../../client/activation/activationService'; import { LanguageServerDownloader } from '../../client/activation/common/downloader'; import { JediExtensionActivator } from '../../client/activation/jedi'; @@ -159,6 +160,7 @@ import { ICryptoUtils, ICurrentProcess, IDataScienceSettings, + IDisposable, IExperimentService, IExperimentsManager, IExtensionContext, @@ -1168,6 +1170,16 @@ export class DataScienceIocContainer extends UnitTestIocContainer { 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(); From 4bfdd6944b7aee4d60e842304b6e603714d89041 Mon Sep 17 00:00:00 2001 From: rchiodo Date: Wed, 22 Jul 2020 15:13:25 -0700 Subject: [PATCH 7/7] Fix hygiene --- src/test/datascience/dataScienceIocContainer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/datascience/dataScienceIocContainer.ts b/src/test/datascience/dataScienceIocContainer.ts index 28c4bf9cbc07..4840870be77f 100644 --- a/src/test/datascience/dataScienceIocContainer.ts +++ b/src/test/datascience/dataScienceIocContainer.ts @@ -20,6 +20,7 @@ import { FileSystemWatcher, Memento, Uri, + WindowState, WorkspaceFolder, WorkspaceFoldersChangeEvent } from 'vscode'; @@ -27,7 +28,6 @@ import * as vsls from 'vsls/vscode'; import { KernelDaemonPool } from '../../client/datascience/kernel-launcher/kernelDaemonPool'; import { promisify } from 'util'; -import { WindowState } from 'vscode'; import { LanguageServerExtensionActivationService } from '../../client/activation/activationService'; import { LanguageServerDownloader } from '../../client/activation/common/downloader'; import { JediExtensionActivator } from '../../client/activation/jedi';