From d517cf0c8c08b77615639f69320c60a76a1a057e Mon Sep 17 00:00:00 2001 From: Charles Gagnon Date: Fri, 17 Jan 2020 07:44:28 -0800 Subject: [PATCH] Fix new editor windows to open with global connection (#8901) * Fix new editor windows to open with global connection * Fix test * Fix tests * Move logic to queryInputFactory * Remove unused function * Remove unneeded check * Add tests --- .../contrib/query/common/queryInputFactory.ts | 31 ++++- .../test/browser/queryInputFactory.test.ts | 107 ++++++++++++++++++ .../workbench/test/workbenchTestServices.ts | 3 + 3 files changed, 137 insertions(+), 4 deletions(-) create mode 100644 src/sql/workbench/contrib/query/test/browser/queryInputFactory.test.ts diff --git a/src/sql/workbench/contrib/query/common/queryInputFactory.ts b/src/sql/workbench/contrib/query/common/queryInputFactory.ts index a9e18b7668..06e14cdf37 100644 --- a/src/sql/workbench/contrib/query/common/queryInputFactory.ts +++ b/src/sql/workbench/contrib/query/common/queryInputFactory.ts @@ -14,6 +14,11 @@ import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileE import { UntitledTextEditorInput } from 'vs/workbench/common/editor/untitledTextEditorInput'; import { ILanguageAssociation } from 'sql/workbench/common/languageAssociation'; import { QueryEditorInput } from 'sql/workbench/contrib/query/common/queryEditorInput'; +import { getCurrentGlobalConnection } from 'sql/workbench/browser/taskUtilities'; +import { IObjectExplorerService } from 'sql/workbench/services/objectExplorer/browser/objectExplorerService'; +import { IConnectionManagementService, IConnectionCompletionOptions, ConnectionType } from 'sql/platform/connection/common/connectionManagement'; +import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { onUnexpectedError } from 'vs/base/common/errors'; const editorInputFactoryRegistry = Registry.as(EditorInputExtensions.EditorInputFactories); @@ -21,17 +26,35 @@ export class QueryEditorLanguageAssociation implements ILanguageAssociation { static readonly isDefault = true; static readonly languages = ['sql']; - constructor(@IInstantiationService private readonly instantiationService: IInstantiationService) { } + constructor(@IInstantiationService private readonly instantiationService: IInstantiationService, + @IObjectExplorerService private readonly objectExplorerService: IObjectExplorerService, + @IConnectionManagementService private readonly connectionManagementService: IConnectionManagementService, + @IEditorService private readonly editorService: IEditorService) { } - convertInput(activeEditor: IEditorInput): QueryEditorInput { + convertInput(activeEditor: IEditorInput): QueryEditorInput | undefined { const queryResultsInput = this.instantiationService.createInstance(QueryResultsInput, activeEditor.getResource().toString(true)); + let queryEditorInput: QueryEditorInput; if (activeEditor instanceof FileEditorInput) { - return this.instantiationService.createInstance(FileQueryEditorInput, '', activeEditor, queryResultsInput); + queryEditorInput = this.instantiationService.createInstance(FileQueryEditorInput, '', activeEditor, queryResultsInput); } else if (activeEditor instanceof UntitledTextEditorInput) { - return this.instantiationService.createInstance(UntitledQueryEditorInput, '', activeEditor, queryResultsInput); + queryEditorInput = this.instantiationService.createInstance(UntitledQueryEditorInput, '', activeEditor, queryResultsInput); } else { return undefined; } + + const profile = getCurrentGlobalConnection(this.objectExplorerService, this.connectionManagementService, this.editorService); + if (profile) { + const options: IConnectionCompletionOptions = { + params: { connectionType: ConnectionType.editor, runQueryOnCompletion: undefined, input: queryEditorInput }, + saveTheConnection: false, + showDashboard: false, + showConnectionDialogOnError: true, + showFirewallRuleOnError: true + }; + this.connectionManagementService.connect(profile, queryEditorInput.uri, options).catch(err => onUnexpectedError(err)); + } + + return queryEditorInput; } createBase(activeEditor: QueryEditorInput): IEditorInput { diff --git a/src/sql/workbench/contrib/query/test/browser/queryInputFactory.test.ts b/src/sql/workbench/contrib/query/test/browser/queryInputFactory.test.ts new file mode 100644 index 0000000000..23a316e1bb --- /dev/null +++ b/src/sql/workbench/contrib/query/test/browser/queryInputFactory.test.ts @@ -0,0 +1,107 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import { TestEditorService } from 'vs/workbench/test/workbenchTestServices'; +import { URI } from 'vs/base/common/uri'; +import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { IEditorInput } from 'vs/workbench/common/editor'; +import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput'; +import { workbenchInstantiationService } from 'sql/workbench/test/workbenchTestServices'; +import { QueryEditorLanguageAssociation } from 'sql/workbench/contrib/query/common/queryInputFactory'; +import { IObjectExplorerService } from 'sql/workbench/services/objectExplorer/browser/objectExplorerService'; +import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile'; +import { TestObjectExplorerService } from 'sql/workbench/services/objectExplorer/test/browser/testObjectExplorerService'; +import { TestConnectionManagementService } from 'sql/platform/connection/test/common/testConnectionManagementService'; +import { IConnectionProfile } from 'sql/platform/connection/common/interfaces'; +import { IConnectionManagementService, IConnectionCompletionOptions, IConnectionCallbacks, IConnectionResult } from 'sql/platform/connection/common/connectionManagement'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { UntitledQueryEditorInput } from 'sql/workbench/contrib/query/common/untitledQueryEditorInput'; +import { UntitledTextEditorInput } from 'vs/workbench/common/editor/untitledTextEditorInput'; + +suite('Query Input Factory', () => { + + test('query editor input is connected if global connection exists (OE)', () => { + const editorService = new MockEditorService(); + const instantiationService = workbenchInstantiationService(); + const connectionManagementService = new MockConnectionManagementService(); + instantiationService.stub(IObjectExplorerService, new MockObjectExplorerService()); + instantiationService.stub(IConnectionManagementService, connectionManagementService); + instantiationService.stub(IEditorService, editorService); + const queryEditorLanguageAssociation = instantiationService.createInstance(QueryEditorLanguageAssociation); + const input = instantiationService.createInstance(FileEditorInput, URI.file('/test/file.sql'), undefined, undefined); + queryEditorLanguageAssociation.convertInput(input); + assert(connectionManagementService.numberConnects === 1, 'Convert input should have called connect when active OE connection exists'); + }); + + test('query editor input is connected if global connection exists (Editor)', () => { + const instantiationService = workbenchInstantiationService(); + const editorService = new MockEditorService(instantiationService); + const connectionManagementService = new MockConnectionManagementService(); + instantiationService.stub(IObjectExplorerService, new MockObjectExplorerService()); + instantiationService.stub(IConnectionManagementService, connectionManagementService); + instantiationService.stub(IEditorService, editorService); + const queryEditorLanguageAssociation = instantiationService.createInstance(QueryEditorLanguageAssociation); + const input = instantiationService.createInstance(FileEditorInput, URI.file('/test/file.sql'), undefined, undefined); + queryEditorLanguageAssociation.convertInput(input); + assert(connectionManagementService.numberConnects === 1, 'Convert input should have called connect when active editor connection exists'); + }); + + test('query editor input is not connected if no global connection exists', () => { + const instantiationService = workbenchInstantiationService(); + const editorService = new MockEditorService(); + const connectionManagementService = new MockConnectionManagementService(); + instantiationService.stub(IConnectionManagementService, connectionManagementService); + instantiationService.stub(IEditorService, editorService); + const queryEditorLanguageAssociation = instantiationService.createInstance(QueryEditorLanguageAssociation); + const input = instantiationService.createInstance(FileEditorInput, URI.file('/test/file.sql'), undefined, undefined); + queryEditorLanguageAssociation.convertInput(input); + assert(connectionManagementService.numberConnects === 0, 'Convert input should not have been called connect when no global connections exist'); + }); + +}); + +class MockEditorService extends TestEditorService { + public readonly activeEditor: IEditorInput | undefined = undefined; + + constructor(instantiationService?: IInstantiationService) { + super(); + if (instantiationService) { + const untitledInput = instantiationService.createInstance(UntitledTextEditorInput, URI.file('/test/file'), false, undefined, undefined, undefined); + this.activeEditor = instantiationService.createInstance(UntitledQueryEditorInput, '', untitledInput, undefined); + } + } +} + +class MockObjectExplorerService extends TestObjectExplorerService { + public getSelectedProfileAndDatabase(): { profile: ConnectionProfile, databaseName: string } { + return { + profile: {}, // Not actually used so fine to cast + databaseName: '' + }; + } + + public isFocused(): boolean { + return true; + } +} + +class MockConnectionManagementService extends TestConnectionManagementService { + + public numberConnects = 0; + + public isProfileConnected(connectionProfile: IConnectionProfile): boolean { + return true; + } + + public connect(connection: IConnectionProfile, uri: string, options?: IConnectionCompletionOptions, callbacks?: IConnectionCallbacks): Promise { + this.numberConnects++; + return Promise.resolve(undefined); + } + + public getConnectionProfile(fileUri: string): IConnectionProfile { + return {}; // Not actually used so fine to cast + } +} diff --git a/src/sql/workbench/test/workbenchTestServices.ts b/src/sql/workbench/test/workbenchTestServices.ts index dc82516cd0..fd40230291 100644 --- a/src/sql/workbench/test/workbenchTestServices.ts +++ b/src/sql/workbench/test/workbenchTestServices.ts @@ -8,10 +8,13 @@ import { IQueryModelService } from 'sql/platform/query/common/queryModel'; import { TestQueryModelService } from 'sql/platform/query/test/common/testQueryModelService'; import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement'; import { TestConnectionManagementService } from 'sql/platform/connection/test/common/testConnectionManagementService'; +import { TestObjectExplorerService } from 'sql/workbench/services/objectExplorer/test/browser/testObjectExplorerService'; +import { IObjectExplorerService } from 'sql/workbench/services/objectExplorer/browser/objectExplorerService'; export function workbenchInstantiationService(): ITestInstantiationService { const instantiationService = vsworkbenchInstantiationService(); instantiationService.stub(IConnectionManagementService, new TestConnectionManagementService()); instantiationService.stub(IQueryModelService, new TestQueryModelService()); + instantiationService.stub(IObjectExplorerService, new TestObjectExplorerService()); return instantiationService; }