mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-14 12:08:36 -05:00
[Notebook] Run Parameters Action openNotebook Functionality in Core (#14978)
* NotebookService update * openNotebook functionality in NbService * Add tests for RunParametersAction
This commit is contained in:
@@ -13,6 +13,7 @@ import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileE
|
||||
import { UntitledTextEditorInput } from 'vs/workbench/services/untitled/common/untitledTextEditorInput';
|
||||
import { ILanguageAssociation } from 'sql/workbench/services/languageAssociation/common/languageAssociation';
|
||||
import { NotebookInput } from 'sql/workbench/contrib/notebook/browser/models/notebookInput';
|
||||
import { NotebookLanguage } from 'sql/workbench/common/constants';
|
||||
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
|
||||
import { DiffNotebookInput } from 'sql/workbench/contrib/notebook/browser/models/diffNotebookInput';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
@@ -20,7 +21,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
|
||||
const editorInputFactoryRegistry = Registry.as<IEditorInputFactoryRegistry>(EditorInputExtensions.EditorInputFactories);
|
||||
|
||||
export class NotebookEditorInputAssociation implements ILanguageAssociation {
|
||||
static readonly languages = ['notebook', 'ipynb'];
|
||||
static readonly languages = [NotebookLanguage.Notebook, NotebookLanguage.Ipynb];
|
||||
|
||||
constructor(@IInstantiationService private readonly instantiationService: IInstantiationService, @IConfigurationService private readonly configurationService: IConfigurationService) { }
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel'
|
||||
import { NotebookFindModel } from 'sql/workbench/contrib/notebook/browser/find/notebookFindModel';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { NotebookModel } from 'sql/workbench/services/notebook/browser/models/notebookModel';
|
||||
import { INotebookInput } from 'sql/workbench/services/notebook/browser/interface';
|
||||
|
||||
export type ModeViewSaveHandler = (handle: number) => Thenable<boolean>;
|
||||
|
||||
@@ -209,7 +210,7 @@ export class NotebookEditorModel extends EditorModel {
|
||||
|
||||
type TextInput = ResourceEditorInput | UntitledTextEditorInput | FileEditorInput;
|
||||
|
||||
export abstract class NotebookInput extends EditorInput {
|
||||
export abstract class NotebookInput extends EditorInput implements INotebookInput {
|
||||
private _providerId: string;
|
||||
private _providers: string[];
|
||||
private _standardKernels: IStandardKernelWithProvider[];
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import * as path from 'vs/base/common/path';
|
||||
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { localize } from 'vs/nls';
|
||||
@@ -361,14 +362,14 @@ export class RunParametersAction extends TooltipFromLabelAction {
|
||||
* (showNotebookDocument to be utilized in Notebook Service)
|
||||
**/
|
||||
public async openParameterizedNotebook(uri: URI): Promise<void> {
|
||||
// const editor = this._notebookService.findNotebookEditor(uri);
|
||||
// let modelContents = editor.model.toJSON();
|
||||
// let basename = path.basename(uri.fsPath);
|
||||
// let untitledUri = uri.with({ authority: '', scheme: 'untitled', path: basename });
|
||||
// this._notebookService.showNotebookDocument(untitledUri, {
|
||||
// initialContent: modelContents,
|
||||
// preserveFocus: true
|
||||
// });
|
||||
const editor = this._notebookService.findNotebookEditor(uri);
|
||||
let modelContents = JSON.stringify(editor.model.toJSON());
|
||||
let basename = path.basename(uri.fsPath);
|
||||
let untitledUri = uri.with({ authority: '', scheme: 'untitled', path: basename });
|
||||
this._notebookService.openNotebook(untitledUri, {
|
||||
initialContent: modelContents,
|
||||
preserveFocus: true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { ViewPaneContainer, ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
||||
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||
import { NotebookSearchWidget, INotebookExplorerSearchOptions } from 'sql/workbench/contrib/notebook/browser/notebookExplorer/notebookSearchWidget';
|
||||
import * as Constants from 'sql/workbench/contrib/notebook/common/constants';
|
||||
import * as Constants from 'sql/workbench/common/constants';
|
||||
import { IChangeEvent } from 'vs/workbench/contrib/search/common/searchModel';
|
||||
import { Delayer } from 'vs/base/common/async';
|
||||
import { ITextQuery, IPatternInfo } from 'vs/workbench/services/search/common/search';
|
||||
|
||||
@@ -16,7 +16,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
|
||||
import * as Constants from 'sql/workbench/contrib/notebook/common/constants';
|
||||
import * as Constants from 'sql/workbench/common/constants';
|
||||
import { IMessage } from 'vs/base/browser/ui/inputbox/inputBox';
|
||||
import { appendKeyBindingLabel } from 'vs/workbench/contrib/search/browser/searchActions';
|
||||
import { ContextScopedFindInput } from 'vs/platform/browser/contextScopedHistoryWidget';
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import * as glob from 'vs/base/common/glob';
|
||||
import { SearchSortOrder } from 'vs/workbench/services/search/common/search';
|
||||
|
||||
export const FindInNotebooksActionId = 'workbench.action.findInNotebooks';
|
||||
export const FocusActiveEditorCommandId = 'notebookSearch.action.focusActiveEditor';
|
||||
|
||||
export const FocusSearchFromResults = 'notebookSearch.action.focusSearchFromResults';
|
||||
export const OpenMatchToSide = 'notebookSearch.action.openResultToSide';
|
||||
export const CancelActionId = 'notebookSearch.action.cancel';
|
||||
export const RemoveActionId = 'notebookSearch.action.remove';
|
||||
export const CopyPathCommandId = 'notebookSearch.action.copyPath';
|
||||
export const CopyMatchCommandId = 'notebookSearch.action.copyMatch';
|
||||
export const CopyAllCommandId = 'notebookSearch.action.copyAll';
|
||||
export const OpenInEditorCommandId = 'notebookSearch.action.openInEditor';
|
||||
export const ClearSearchHistoryCommandId = 'notebookSearch.action.clearHistory';
|
||||
export const FocusSearchListCommandID = 'notebookSearch.action.focusSearchList';
|
||||
export const ToggleCaseSensitiveCommandId = 'toggleSearchCaseSensitive';
|
||||
export const ToggleWholeWordCommandId = 'toggleSearchWholeWord';
|
||||
export const ToggleRegexCommandId = 'toggleSearchRegex';
|
||||
export const AddCursorsAtSearchResults = 'addCursorsAtSearchResults';
|
||||
|
||||
export const SearchViewFocusedKey = new RawContextKey<boolean>('notebookSearchViewletFocus', false);
|
||||
export const InputBoxFocusedKey = new RawContextKey<boolean>('inputBoxFocus', false);
|
||||
export const SearchInputBoxFocusedKey = new RawContextKey<boolean>('searchInputBoxFocus', false);
|
||||
|
||||
export interface INotebookSearchConfigurationProperties {
|
||||
exclude: glob.IExpression;
|
||||
useRipgrep: boolean;
|
||||
/**
|
||||
* Use ignore file for file search.
|
||||
*/
|
||||
useIgnoreFiles: boolean;
|
||||
useGlobalIgnoreFiles: boolean;
|
||||
followSymlinks: boolean;
|
||||
smartCase: boolean;
|
||||
globalFindClipboard: boolean;
|
||||
location: 'sidebar' | 'panel';
|
||||
useReplacePreview: boolean;
|
||||
showLineNumbers: boolean;
|
||||
usePCRE2: boolean;
|
||||
actionsPosition: 'auto' | 'right';
|
||||
maintainFileSearchCache: boolean;
|
||||
collapseResults: 'auto' | 'alwaysCollapse' | 'alwaysExpand';
|
||||
searchOnType: boolean;
|
||||
seedOnFocus: boolean;
|
||||
seedWithNearestWord: boolean;
|
||||
searchOnTypeDebouncePeriod: number;
|
||||
searchEditor: {
|
||||
doubleClickBehaviour: 'selectWord' | 'goToLocation' | 'openLocationToSide',
|
||||
experimental: { reusePriorSearchConfiguration: boolean }
|
||||
};
|
||||
sortOrder: SearchSortOrder;
|
||||
}
|
||||
@@ -113,7 +113,10 @@ suite('CellToolbarActions', function (): void {
|
||||
undefined,
|
||||
undefined,
|
||||
new MockContextKeyService(),
|
||||
instantiationService.get(IProductService)
|
||||
instantiationService.get(IProductService),
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
instantiationService.stub(INotificationService, new TestNotificationService());
|
||||
instantiationService.stub(INotebookService, notebookService);
|
||||
|
||||
@@ -67,7 +67,10 @@ suite('MarkdownTextTransformer', () => {
|
||||
undefined,
|
||||
undefined,
|
||||
new MockContextKeyService(),
|
||||
instantiationService.get(IProductService)
|
||||
instantiationService.get(IProductService),
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
mockNotebookService = TypeMoq.Mock.ofInstance(notebookService);
|
||||
|
||||
|
||||
@@ -13,19 +13,20 @@ import { NotebookEditorStub } from 'sql/workbench/contrib/notebook/test/testComm
|
||||
import { ICellModel, INotebookModel } from 'sql/workbench/services/notebook/browser/models/modelInterfaces';
|
||||
import { IStandardKernelWithProvider } from 'sql/workbench/services/notebook/browser/models/notebookUtils';
|
||||
import { INotebookEditor, INotebookService } from 'sql/workbench/services/notebook/browser/notebookService';
|
||||
import { CellType } from 'sql/workbench/services/notebook/common/contracts';
|
||||
import { CellType, CellTypes } from 'sql/workbench/services/notebook/common/contracts';
|
||||
import * as TypeMoq from 'typemoq';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { TestCommandService } from 'vs/editor/test/browser/editorTestServices';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IConfigurationChangeEvent, IConfigurationOverrides, IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
|
||||
import { workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { NullAdsTelemetryService } from 'sql/platform/telemetry/common/adsTelemetryService';
|
||||
import { MockQuickInputService } from 'sql/workbench/contrib/notebook/test/common/quickInputServiceMock';
|
||||
import { localize } from 'vs/nls';
|
||||
|
||||
class TestClientSession extends ClientSessionStub {
|
||||
private _errorState: boolean = false;
|
||||
@@ -259,22 +260,91 @@ suite('Notebook Actions', function (): void {
|
||||
assert.strictEqual(actualCmdId, NewNotebookAction.INTERNAL_NEW_NOTEBOOK_CMD_ID);
|
||||
});
|
||||
|
||||
test.skip('Run with Parameters Action', async function (): Promise<void> {
|
||||
test('Run with Parameters Action', async function (): Promise<void> {
|
||||
const testContents: azdata.nb.INotebookContents = {
|
||||
cells: [{
|
||||
cell_type: CellTypes.Code,
|
||||
source: ['x=2.0\n', 'y=5.0'],
|
||||
metadata: { language: 'python' },
|
||||
execution_count: 1
|
||||
}],
|
||||
metadata: {
|
||||
kernelspec: {
|
||||
name: 'python',
|
||||
language: 'python',
|
||||
display_name: 'Python 3'
|
||||
}
|
||||
},
|
||||
nbformat: 4,
|
||||
nbformat_minor: 5
|
||||
};
|
||||
|
||||
let mockNotification = TypeMoq.Mock.ofType<INotificationService>(TestNotificationService);
|
||||
mockNotification.setup(n => n.notify(TypeMoq.It.isAny()));
|
||||
let quickInputService = new MockQuickInputService;
|
||||
let mockNotebookModel = new NotebookModelStub(undefined, undefined, testContents);
|
||||
|
||||
let action = new RunParametersAction('TestId', true, testUri, quickInputService, mockNotebookService.object, mockNotification.object);
|
||||
|
||||
// Normal use case
|
||||
const testCells = [<ICellModel>{
|
||||
isParameter: true,
|
||||
source: ['x=2.0\n', 'y=5.0']
|
||||
}];
|
||||
|
||||
mockNotebookEditor.setup(x => x.model).returns(() => mockNotebookModel);
|
||||
mockNotebookEditor.setup(x => x.cells).returns(() => testCells);
|
||||
|
||||
assert.doesNotThrow(() => action.run(testUri));
|
||||
// Run Parameters Action
|
||||
await action.run(testUri);
|
||||
let testShowOptions = {
|
||||
initialContent: JSON.stringify(mockNotebookModel.toJSON()),
|
||||
preserveFocus: true
|
||||
};
|
||||
assert.call(mockNotebookService.object.openNotebook(testUri, testShowOptions), 'Should Open Parameterized Notebook');
|
||||
});
|
||||
|
||||
test('Run with Parameters Action with no parameters in notebook', async function (): Promise<void> {
|
||||
const testContents: azdata.nb.INotebookContents = {
|
||||
cells: [{
|
||||
cell_type: CellTypes.Code,
|
||||
source: [''],
|
||||
metadata: { language: 'python' },
|
||||
execution_count: 1
|
||||
}],
|
||||
metadata: {
|
||||
kernelspec: {
|
||||
name: 'python',
|
||||
language: 'python',
|
||||
display_name: 'Python 3'
|
||||
}
|
||||
},
|
||||
nbformat: 4,
|
||||
nbformat_minor: 5
|
||||
};
|
||||
let expectedMsg: string = localize('noParametersCell', "This notebook cannot run with parameters until a parameter cell is added. [Learn more](https://docs.microsoft.com/sql/azure-data-studio/notebooks/notebooks-parameterization).");
|
||||
let notification = {
|
||||
severity: Severity.Info,
|
||||
message: expectedMsg,
|
||||
};
|
||||
|
||||
let actualMsg: string;
|
||||
let mockNotification = TypeMoq.Mock.ofType<INotificationService>(TestNotificationService);
|
||||
mockNotification.setup(n => n.notify(TypeMoq.It.isAny())).returns(notification => {
|
||||
actualMsg = notification.message;
|
||||
return undefined;
|
||||
});
|
||||
let quickInputService = new MockQuickInputService;
|
||||
let mockNotebookModel = new NotebookModelStub(undefined, undefined, testContents);
|
||||
|
||||
let action = new RunParametersAction('TestId', true, testUri, quickInputService, mockNotebookService.object, mockNotification.object);
|
||||
|
||||
mockNotebookEditor.setup(x => x.model).returns(() => mockNotebookModel);
|
||||
|
||||
// Run Parameters Action
|
||||
await action.run(testUri);
|
||||
|
||||
assert.ok(actualMsg !== undefined, 'Should have received a notification');
|
||||
assert.call(mockNotification.object.notify(notification), 'Should notify user there is no parameter cell');
|
||||
assert.strictEqual(actualMsg, expectedMsg);
|
||||
});
|
||||
|
||||
suite('Kernels dropdown', async () => {
|
||||
|
||||
@@ -697,7 +697,10 @@ function setupServices(arg: { workbenchThemeService?: WorkbenchThemeService, ins
|
||||
instantiationService.get(ILogService),
|
||||
queryManagementService,
|
||||
instantiationService.get(IContextKeyService),
|
||||
instantiationService.get(IProductService)
|
||||
instantiationService.get(IProductService),
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
||||
instantiationService.stub(INotebookService, notebookService);
|
||||
|
||||
@@ -30,6 +30,9 @@ import { ExtensionManagementService } from 'vs/workbench/services/extensionManag
|
||||
import { TestFileService, TestLifecycleService } from 'vs/workbench/test/browser/workbenchTestServices';
|
||||
import { TestExtensionService, TestStorageService } from 'vs/workbench/test/common/workbenchTestServices';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IUntitledTextEditorService } from 'vs/workbench/services/untitled/common/untitledTextEditorService';
|
||||
|
||||
/**
|
||||
* class to mock azdata.nb.ServerManager object
|
||||
@@ -109,6 +112,9 @@ suite.skip('NotebookService:', function (): void {
|
||||
let testNo = 0;
|
||||
let sandbox: sinon.SinonSandbox;
|
||||
let productService: IProductService;
|
||||
let editorService: IEditorService;
|
||||
let untitledTextEditorService: IUntitledTextEditorService;
|
||||
let editorGroupsService: IEditorGroupsService;
|
||||
|
||||
let installExtensionEmitter: Emitter<InstallExtensionEvent>,
|
||||
didInstallExtensionEmitter: Emitter<DidInstallExtensionEvent>,
|
||||
@@ -147,8 +153,13 @@ suite.skip('NotebookService:', function (): void {
|
||||
|
||||
instantiationService.stub(IProductService, { quality: 'stable' });
|
||||
productService = instantiationService.get(IProductService);
|
||||
editorService = new IEditorService;
|
||||
untitledTextEditorService = new IUntitledTextEditorService;
|
||||
editorGroupsService = new IEditorGroupsService;
|
||||
|
||||
notebookService = new NotebookService(lifecycleService, storageService, extensionServiceMock.object, extensionManagementService, instantiationService, fileService, logServiceMock.object, queryManagementService, contextService, productService);
|
||||
notebookService = new NotebookService(lifecycleService, storageService, extensionServiceMock.object, extensionManagementService,
|
||||
instantiationService, fileService, logServiceMock.object, queryManagementService, contextService, productService,
|
||||
editorService, untitledTextEditorService, editorGroupsService);
|
||||
sandbox = sinon.sandbox.create();
|
||||
});
|
||||
|
||||
@@ -446,7 +457,7 @@ suite.skip('NotebookService:', function (): void {
|
||||
};
|
||||
errorHandler.setUnexpectedErrorHandler(onUnexpectedErrorVerifier);
|
||||
// The following call throws an exception internally with queryManagementService parameter being undefined.
|
||||
new NotebookService(lifecycleService, storageService, extensionService, extensionManagementService, instantiationService, fileService, logService, /* queryManagementService */ undefined, contextService, productService);
|
||||
new NotebookService(lifecycleService, storageService, extensionService, extensionManagementService, instantiationService, fileService, logService, /* queryManagementService */ undefined, contextService, productService, editorService, untitledTextEditorService, editorGroupsService);
|
||||
await unexpectedErrorPromise;
|
||||
assert.strictEqual(unexpectedErrorCalled, true, `onUnexpectedError must be have been raised when queryManagementService is undefined when calling NotebookService constructor`);
|
||||
});
|
||||
|
||||
@@ -117,7 +117,10 @@ suite('Notebook Editor Model', function (): void {
|
||||
undefined,
|
||||
undefined,
|
||||
new MockContextKeyService(),
|
||||
testinstantiationService.get(IProductService)
|
||||
testinstantiationService.get(IProductService),
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
let mockNotebookService = TypeMoq.Mock.ofInstance(notebookService);
|
||||
|
||||
|
||||
@@ -14,12 +14,14 @@ import { IModelDecorationsChangeAccessor } from 'vs/editor/common/model';
|
||||
import { NotebookFindMatch } from 'sql/workbench/contrib/notebook/browser/find/notebookFindDecorations';
|
||||
import { RenderMimeRegistry } from 'sql/workbench/services/notebook/browser/outputs/registry';
|
||||
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { QueryTextEditor } from 'sql/workbench/browser/modelComponents/queryTextEditor';
|
||||
import { IContextViewProvider, IDelegate } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { IEditorPane } from 'vs/workbench/common/editor';
|
||||
import { INotebookShowOptions } from 'sql/workbench/api/common/sqlExtHost.protocol';
|
||||
|
||||
export class NotebookModelStub implements INotebookModel {
|
||||
constructor(private _languageInfo?: nb.ILanguageInfo, private _cells?: ICellModel[]) {
|
||||
constructor(private _languageInfo?: nb.ILanguageInfo, private _cells?: ICellModel[], private _testContents?: nb.INotebookContents) {
|
||||
}
|
||||
trustedMode: boolean;
|
||||
language: string;
|
||||
@@ -134,7 +136,7 @@ export class NotebookModelStub implements INotebookModel {
|
||||
throw new Error('method not implemented.');
|
||||
}
|
||||
toJSON(): nb.INotebookContents {
|
||||
throw new Error('Method not implemented.');
|
||||
return this._testContents;
|
||||
}
|
||||
serializationStateChanged(changeType: NotebookChangeType, cell?: ICellModel): void {
|
||||
throw new Error('Method not implemented.');
|
||||
@@ -292,6 +294,9 @@ export class NotebookServiceStub implements INotebookService {
|
||||
navigateTo(notebookUri: URI, sectionId: string): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
openNotebook(resource: UriComponents, options: INotebookShowOptions): Promise<IEditorPane> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
get onCodeCellExecutionStart(): vsEvent.Event<void> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user