From 15bfaa63fdfffc140ba9a75f12106d295187c134 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Tue, 10 Mar 2020 14:34:57 -0700 Subject: [PATCH 1/4] Fix tests --- .../interactive-ipynb/nativeEditorProvider.unit.test.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/test/datascience/interactive-ipynb/nativeEditorProvider.unit.test.ts b/src/test/datascience/interactive-ipynb/nativeEditorProvider.unit.test.ts index 6ba23687e933..49fbb8c939b2 100644 --- a/src/test/datascience/interactive-ipynb/nativeEditorProvider.unit.test.ts +++ b/src/test/datascience/interactive-ipynb/nativeEditorProvider.unit.test.ts @@ -9,7 +9,7 @@ import { expect } from 'chai'; import { anything, instance, mock, when } from 'ts-mockito'; import * as typemoq from 'typemoq'; import { EventEmitter, Uri, WebviewPanel } from 'vscode'; -import { ICustomEditorService, IWorkspaceService } from '../../../client/common/application/types'; +import { CustomDocument, ICustomEditorService, IWorkspaceService } from '../../../client/common/application/types'; import { WorkspaceService } from '../../../client/common/application/workspace'; import { AsyncDisposableRegistry } from '../../../client/common/asyncDisposableRegistry'; import { ConfigurationService } from '../../../client/common/configuration/service'; @@ -65,10 +65,13 @@ suite('Data Science - Native Editor Provider', () => { .returns((_a1, _a2, _a3) => { return { dispose: noop }; }); + customEditorService .setup(c => c.openEditor(typemoq.It.isAny())) .returns(async f => { - return registeredProvider.resolveCustomEditor(f, panel.object); + const doc = typemoq.Mock.ofType(); + doc.setup(d => d.uri).returns(() => f); + return registeredProvider.resolveCustomEditor(doc.object, panel.object); }); editor From be143e66d47c0e222a003d6aa2813f71f9e2fba0 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Tue, 10 Mar 2020 14:47:21 -0700 Subject: [PATCH 2/4] Revert "Disable proposed api used for custom editor" This reverts commit e93f77ab11e68aeeeb81f82b0632cefd24cecef5. --- .vscode/launch.json | 4 +- .../insidersBuild/insidersExtensionService.ts | 5 +- .../insidersExtensionService.unit.test.ts | 6 + src/test/debuggerTest.ts | 3 +- src/test/multiRootTest.ts | 5 +- src/test/standardTest.ts | 5 +- types/vscode.proposed.d.ts | 119 ++++++++++++++++++ 7 files changed, 140 insertions(+), 7 deletions(-) create mode 100644 types/vscode.proposed.d.ts diff --git a/.vscode/launch.json b/.vscode/launch.json index 39f2c4888690..c84950536f9a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,7 +8,9 @@ "request": "launch", "runtimeExecutable": "${execPath}", "args": [ - "--extensionDevelopmentPath=${workspaceFolder}" + "--extensionDevelopmentPath=${workspaceFolder}", + "--enable-proposed-api", + "ms-python.python" ], "stopOnEntry": false, "smartStep": true, diff --git a/src/client/common/insidersBuild/insidersExtensionService.ts b/src/client/common/insidersBuild/insidersExtensionService.ts index 6cdd2e908559..00f34c151793 100644 --- a/src/client/common/insidersBuild/insidersExtensionService.ts +++ b/src/client/common/insidersBuild/insidersExtensionService.ts @@ -85,7 +85,10 @@ export class InsidersExtensionService implements IExtensionSingleActivationServi * @returns `true` if install channel is handled in these miscellaneous cases, `false` if install channel needs further handling */ public async handleEdgeCases(installChannel: ExtensionChannels, isDefault: boolean): Promise { - if (await this.promptToInstallInsidersIfApplicable(isDefault)) { + // When running UI Tests we might want to disable these prompts. + if (process.env.UITEST_DISABLE_INSIDERS) { + return true; + } else if (await this.promptToInstallInsidersIfApplicable(isDefault)) { return true; } else if (await this.setInsidersChannelToOffIfApplicable(installChannel)) { return true; diff --git a/src/test/common/insidersBuild/insidersExtensionService.unit.test.ts b/src/test/common/insidersBuild/insidersExtensionService.unit.test.ts index 7a14271c3a46..9801cddb0825 100644 --- a/src/test/common/insidersBuild/insidersExtensionService.unit.test.ts +++ b/src/test/common/insidersBuild/insidersExtensionService.unit.test.ts @@ -106,7 +106,10 @@ suite('Insiders Extension Service - Activation', () => { let handleEdgeCases: sinon.SinonStub; let insidersInstaller: IExtensionBuildInstaller; let insidersExtensionService: InsidersExtensionService; + let envUITEST_DISABLE_INSIDERSExists = false; setup(() => { + envUITEST_DISABLE_INSIDERSExists = process.env.UITEST_DISABLE_INSIDERS !== undefined; + delete process.env.UITEST_DISABLE_INSIDERS; extensionChannelService = mock(ExtensionChannelService); insidersInstaller = mock(InsidersBuildInstaller); appEnvironment = mock(ApplicationEnvironment); @@ -119,6 +122,9 @@ suite('Insiders Extension Service - Activation', () => { }); teardown(() => { + if (envUITEST_DISABLE_INSIDERSExists) { + process.env.UITEST_DISABLE_INSIDERS = '1'; + } sinon.restore(); }); diff --git a/src/test/debuggerTest.ts b/src/test/debuggerTest.ts index 28a3284fa7fd..810b70ab7946 100644 --- a/src/test/debuggerTest.ts +++ b/src/test/debuggerTest.ts @@ -18,7 +18,8 @@ function start() { extensionDevelopmentPath: EXTENSION_ROOT_DIR_FOR_TESTS, extensionTestsPath: path.join(EXTENSION_ROOT_DIR_FOR_TESTS, 'out', 'test', 'index'), launchArgs: [workspacePath], - version: 'insiders' + version: 'insiders', + extensionTestsEnv: { ...process.env, UITEST_DISABLE_INSIDERS: '1' } }).catch(ex => { console.error('End Debugger tests (with errors)', ex); process.exit(1); diff --git a/src/test/multiRootTest.ts b/src/test/multiRootTest.ts index 0d2ea8ccb4eb..49d74149b26c 100644 --- a/src/test/multiRootTest.ts +++ b/src/test/multiRootTest.ts @@ -13,8 +13,9 @@ function start() { runTests({ extensionDevelopmentPath: EXTENSION_ROOT_DIR_FOR_TESTS, extensionTestsPath: path.join(EXTENSION_ROOT_DIR_FOR_TESTS, 'out', 'test', 'index'), - launchArgs: [workspacePath], - version: 'stable' + launchArgs: [workspacePath, '--enable-proposed-api', 'ms-python.python'], + version: 'insiders', + extensionTestsEnv: { ...process.env, UITEST_DISABLE_INSIDERS: '1' } }).catch(ex => { console.error('End Multiroot tests (with errors)', ex); process.exit(1); diff --git a/src/test/standardTest.ts b/src/test/standardTest.ts index 7fb02edb2bc2..de5d99fa2df2 100644 --- a/src/test/standardTest.ts +++ b/src/test/standardTest.ts @@ -19,8 +19,9 @@ function start() { runTests({ extensionDevelopmentPath: extensionDevelopmentPath, extensionTestsPath: path.join(EXTENSION_ROOT_DIR_FOR_TESTS, 'out', 'test', 'index'), - launchArgs: [workspacePath], - version: 'stable' + launchArgs: [workspacePath, '--enable-proposed-api', 'ms-python.python'], + version: 'insiders', + extensionTestsEnv: { ...process.env, UITEST_DISABLE_INSIDERS: '1' } }).catch(ex => { console.error('End Standard tests (with errors)', ex); process.exit(1); diff --git a/types/vscode.proposed.d.ts b/types/vscode.proposed.d.ts new file mode 100644 index 000000000000..a5eeae0b97f2 --- /dev/null +++ b/types/vscode.proposed.d.ts @@ -0,0 +1,119 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * This is the place for API experiments and proposals. + * These API are NOT stable and subject to change. They are only available in the Insiders + * distribution and CANNOT be used in published extensions. + * + * To test these API in local environment: + * - Use Insiders release of VS Code. + * - Add `"enableProposedApi": true` to your package.json. + * - Copy this file to your project. + */ + +declare module 'vscode' { + + + /** + * Defines the editing functionality of a webview editor. This allows the webview editor to hook into standard + * editor events such as `undo` or `save`. + * + * @param EditType Type of edits. Edit objects must be json serializable. + */ + interface WebviewCustomEditorEditingDelegate { + /** + * Save a resource. + * + * @param resource Resource being saved. + * + * @return Thenable signaling that the save has completed. + */ + save(resource: Uri): Thenable; + + /** + * Save an existing resource at a new path. + * + * @param resource Resource being saved. + * @param targetResource Location to save to. + * + * @return Thenable signaling that the save has completed. + */ + saveAs(resource: Uri, targetResource: Uri): Thenable; + + /** + * Event triggered by extensions to signal to VS Code that an edit has occurred. + */ + readonly onEdit: Event<{ readonly resource: Uri, readonly edit: EditType }>; + + /** + * Apply a set of edits. + * + * Note that is not invoked when `onEdit` is called as `onEdit` implies also updating the view to reflect the edit. + * + * @param resource Resource being edited. + * @param edit Array of edits. Sorted from oldest to most recent. + * + * @return Thenable signaling that the change has completed. + */ + applyEdits(resource: Uri, edits: readonly EditType[]): Thenable; + + /** + * Undo a set of edits. + * + * This is triggered when a user undoes an edit or when revert is called on a file. + * + * @param resource Resource being edited. + * @param edit Array of edits. Sorted from most recent to oldest. + * + * @return Thenable signaling that the change has completed. + */ + undoEdits(resource: Uri, edits: readonly EditType[]): Thenable; + } + + export interface WebviewCustomEditorProvider { + /** + * Resolve a webview editor for a given resource. + * + * To resolve a webview editor, a provider must fill in its initial html content and hook up all + * the event listeners it is interested it. The provider should also take ownership of the passed in `WebviewPanel`. + * + * @param resource Resource being resolved. + * @param webview Webview being resolved. The provider should take ownership of this webview. + * + * @return Thenable indicating that the webview editor has been resolved. + */ + resolveWebviewEditor( + resource: Uri, + webview: WebviewPanel, + ): Thenable; + + /** + * Controls the editing functionality of a webview editor. This allows the webview editor to hook into standard + * editor events such as `undo` or `save`. + * + * WebviewEditors that do not have `editingCapability` are considered to be readonly. Users can still interact + * with readonly editors, but these editors will not integrate with VS Code's standard editor functionality. + */ + readonly editingDelegate?: WebviewCustomEditorEditingDelegate; + } + + namespace window { + /** + * Register a new provider for webview editors of a given type. + * + * @param viewType Type of the webview editor provider. + * @param provider Resolves webview editors. + * @param options Content settings for a webview panels the provider is given. + * + * @return Disposable that unregisters the `WebviewCustomEditorProvider`. + */ + export function registerWebviewCustomEditorProvider( + viewType: string, + provider: WebviewCustomEditorProvider, + options?: WebviewPanelOptions, + ): Disposable; + } +} From 7e3b823371223e492b53c33da8b2dedd93cefa5d Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Tue, 10 Mar 2020 15:03:46 -0700 Subject: [PATCH 3/4] More fixes --- src/datascience-ui/native-editor/nativeCell.tsx | 4 ++-- src/datascience-ui/native-editor/nativeEditor.tsx | 2 +- src/datascience-ui/react-common/constants.ts | 2 +- src/test/datascience/nativeEditor.functional.test.tsx | 3 +++ 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/datascience-ui/native-editor/nativeCell.tsx b/src/datascience-ui/native-editor/nativeCell.tsx index 94756eb9ae7c..2662b627c74f 100644 --- a/src/datascience-ui/native-editor/nativeCell.tsx +++ b/src/datascience-ui/native-editor/nativeCell.tsx @@ -336,7 +336,7 @@ export class NativeCell extends React.Component { break; case 'z': case 'Z': - if (!this.isFocused() && !UseCustomEditor) { + if (!this.isFocused() && !UseCustomEditor.enabled) { if (e.shiftKey && !e.ctrlKey && !e.altKey) { e.stopPropagation(); this.props.redo(); @@ -637,7 +637,7 @@ export class NativeCell extends React.Component { keyDown={this.keyDownInput} showLineNumbers={this.props.cellVM.showLineNumbers} font={this.props.font} - disableUndoStack={UseCustomEditor} + disableUndoStack={UseCustomEditor.enabled} codeVersion={this.props.cellVM.codeVersion ? this.props.cellVM.codeVersion : 1} focusPending={this.props.focusPending} /> diff --git a/src/datascience-ui/native-editor/nativeEditor.tsx b/src/datascience-ui/native-editor/nativeEditor.tsx index 6eb0ba9db4de..d9b62ba01a6a 100644 --- a/src/datascience-ui/native-editor/nativeEditor.tsx +++ b/src/datascience-ui/native-editor/nativeEditor.tsx @@ -193,7 +193,7 @@ ${buildSettingsCss(this.props.settings)}`} } case 'z': case 'Z': - if (!getSelectedAndFocusedInfo(this.props).focusedCellId && !UseCustomEditor) { + if (!getSelectedAndFocusedInfo(this.props).focusedCellId && !UseCustomEditor.enabled) { if (event.shiftKey && !event.ctrlKey && !event.altKey) { event.stopPropagation(); this.props.redo(); diff --git a/src/datascience-ui/react-common/constants.ts b/src/datascience-ui/react-common/constants.ts index 20cd6112d1cb..9ee4d2026375 100644 --- a/src/datascience-ui/react-common/constants.ts +++ b/src/datascience-ui/react-common/constants.ts @@ -24,4 +24,4 @@ export function getOSType() { } } -export const UseCustomEditor = true; +export const UseCustomEditor = { enabled: true }; diff --git a/src/test/datascience/nativeEditor.functional.test.tsx b/src/test/datascience/nativeEditor.functional.test.tsx index fbb31447864e..455ab4927f79 100644 --- a/src/test/datascience/nativeEditor.functional.test.tsx +++ b/src/test/datascience/nativeEditor.functional.test.tsx @@ -36,6 +36,7 @@ import { ExecutionCount } from '../../datascience-ui/interactive-common/executio import { CommonActionType } from '../../datascience-ui/interactive-common/redux/reducers/types'; import { NativeCell } from '../../datascience-ui/native-editor/nativeCell'; import { NativeEditor } from '../../datascience-ui/native-editor/nativeEditor'; +import { UseCustomEditor } from '../../datascience-ui/react-common/constants'; import { IKeyboardEvent } from '../../datascience-ui/react-common/event'; import { ImageButton } from '../../datascience-ui/react-common/imageButton'; import { IMonacoEditorState, MonacoEditor } from '../../datascience-ui/react-common/monacoEditor'; @@ -127,6 +128,7 @@ suite('DataScience Native Editor', () => { }; setup(async () => { + UseCustomEditor.enabled = useCustomEditorApi; ioc = new DataScienceIocContainer(); ioc.registerDataScienceTypes(useCustomEditorApi); @@ -899,6 +901,7 @@ df.head()`; cleanupCallback: Function; }; function initIoc() { + UseCustomEditor.enabled = useCustomEditorApi; ioc = new DataScienceIocContainer(); ioc.registerDataScienceTypes(useCustomEditorApi); } From 2a9fa29dd990acb657f3ea53c0128fbc09df4878 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Tue, 10 Mar 2020 15:05:49 -0700 Subject: [PATCH 4/4] Don't need that --- types/vscode.proposed.d.ts | 119 ------------------------------------- 1 file changed, 119 deletions(-) delete mode 100644 types/vscode.proposed.d.ts diff --git a/types/vscode.proposed.d.ts b/types/vscode.proposed.d.ts deleted file mode 100644 index a5eeae0b97f2..000000000000 --- a/types/vscode.proposed.d.ts +++ /dev/null @@ -1,119 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -/** - * This is the place for API experiments and proposals. - * These API are NOT stable and subject to change. They are only available in the Insiders - * distribution and CANNOT be used in published extensions. - * - * To test these API in local environment: - * - Use Insiders release of VS Code. - * - Add `"enableProposedApi": true` to your package.json. - * - Copy this file to your project. - */ - -declare module 'vscode' { - - - /** - * Defines the editing functionality of a webview editor. This allows the webview editor to hook into standard - * editor events such as `undo` or `save`. - * - * @param EditType Type of edits. Edit objects must be json serializable. - */ - interface WebviewCustomEditorEditingDelegate { - /** - * Save a resource. - * - * @param resource Resource being saved. - * - * @return Thenable signaling that the save has completed. - */ - save(resource: Uri): Thenable; - - /** - * Save an existing resource at a new path. - * - * @param resource Resource being saved. - * @param targetResource Location to save to. - * - * @return Thenable signaling that the save has completed. - */ - saveAs(resource: Uri, targetResource: Uri): Thenable; - - /** - * Event triggered by extensions to signal to VS Code that an edit has occurred. - */ - readonly onEdit: Event<{ readonly resource: Uri, readonly edit: EditType }>; - - /** - * Apply a set of edits. - * - * Note that is not invoked when `onEdit` is called as `onEdit` implies also updating the view to reflect the edit. - * - * @param resource Resource being edited. - * @param edit Array of edits. Sorted from oldest to most recent. - * - * @return Thenable signaling that the change has completed. - */ - applyEdits(resource: Uri, edits: readonly EditType[]): Thenable; - - /** - * Undo a set of edits. - * - * This is triggered when a user undoes an edit or when revert is called on a file. - * - * @param resource Resource being edited. - * @param edit Array of edits. Sorted from most recent to oldest. - * - * @return Thenable signaling that the change has completed. - */ - undoEdits(resource: Uri, edits: readonly EditType[]): Thenable; - } - - export interface WebviewCustomEditorProvider { - /** - * Resolve a webview editor for a given resource. - * - * To resolve a webview editor, a provider must fill in its initial html content and hook up all - * the event listeners it is interested it. The provider should also take ownership of the passed in `WebviewPanel`. - * - * @param resource Resource being resolved. - * @param webview Webview being resolved. The provider should take ownership of this webview. - * - * @return Thenable indicating that the webview editor has been resolved. - */ - resolveWebviewEditor( - resource: Uri, - webview: WebviewPanel, - ): Thenable; - - /** - * Controls the editing functionality of a webview editor. This allows the webview editor to hook into standard - * editor events such as `undo` or `save`. - * - * WebviewEditors that do not have `editingCapability` are considered to be readonly. Users can still interact - * with readonly editors, but these editors will not integrate with VS Code's standard editor functionality. - */ - readonly editingDelegate?: WebviewCustomEditorEditingDelegate; - } - - namespace window { - /** - * Register a new provider for webview editors of a given type. - * - * @param viewType Type of the webview editor provider. - * @param provider Resolves webview editors. - * @param options Content settings for a webview panels the provider is given. - * - * @return Disposable that unregisters the `WebviewCustomEditorProvider`. - */ - export function registerWebviewCustomEditorProvider( - viewType: string, - provider: WebviewCustomEditorProvider, - options?: WebviewPanelOptions, - ): Disposable; - } -}