diff --git a/src/sql/workbench/contrib/query/browser/queryActions.ts b/src/sql/workbench/contrib/query/browser/queryActions.ts index faf8e2de18b9..85e1f8e8971a 100644 --- a/src/sql/workbench/contrib/query/browser/queryActions.ts +++ b/src/sql/workbench/contrib/query/browser/queryActions.ts @@ -242,8 +242,8 @@ export class RunQueryAction extends QueryTaskbarAction { if (this.isConnected(editor)) { // if the selection isn't empty then execute the selection // otherwise, either run the statement or the script depending on parameter - let selection = editor.getSelection(); - if (runCurrentStatement && selection) { + let selection = editor.getSelection(false); + if (runCurrentStatement && selection && this.isCursorPosition(selection)) { editor.input.runQueryStatement(selection); } else { // get the selection again this time with trimming @@ -252,6 +252,11 @@ export class RunQueryAction extends QueryTaskbarAction { } } } + + protected isCursorPosition(selection: IRange) { + return selection.startLineNumber === selection.endLineNumber + && selection.startColumn === selection.endColumn; + } } /** diff --git a/src/sql/workbench/contrib/query/test/browser/queryActions.test.ts b/src/sql/workbench/contrib/query/test/browser/queryActions.test.ts index a42fb2c2c2e0..b3b4e042bea6 100644 --- a/src/sql/workbench/contrib/query/test/browser/queryActions.test.ts +++ b/src/sql/workbench/contrib/query/test/browser/queryActions.test.ts @@ -560,6 +560,124 @@ suite('SQL QueryAction Tests', () => { // ... The connection should have changed to the provided database assert.equal(listItem.currentDatabaseName, eventParams.connectionProfile.databaseName); }); + + test('runCurrent - opens connection dialog when there are no active connections', async () => { + // setting up environment + let isConnected = false; + let predefinedSelection: IRange = { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 }; + let calledRunQueryStatementOnInput: boolean = undefined; + + // mocking query editor + const contextkeyservice = new MockContextKeyService(); + let queryEditor = TypeMoq.Mock.ofType(QueryEditor, TypeMoq.MockBehavior.Loose, undefined, new TestThemeService(), + new TestStorageService(), contextkeyservice, undefined, new TestFileService(), undefined); + queryEditor.setup(x => x.input).returns(() => testQueryInput.object); + queryEditor.setup(x => x.getSelection(false)).returns(() => { return predefinedSelection; }); + + // Mocking runQueryStatment in unititledQueryEditorInput + testQueryInput.setup(x => x.runQueryStatement(TypeMoq.It.isAny())).callback(() => { calledRunQueryStatementOnInput = true; }); + + // mocking isConnected in ConnectionManagementService + connectionManagementService.setup(x => x.isConnected(TypeMoq.It.isAnyString())).returns(() => isConnected); + + // mocking QueryModelService + let queryModelService = TypeMoq.Mock.ofType(QueryModelService, TypeMoq.MockBehavior.Loose); + queryModelService.setup(x => x.runQueryStatement(TypeMoq.It.isAny(), TypeMoq.It.isAny())); + + // Calling runCurrent with no open connection + let queryAction: RunQueryAction = new RunQueryAction(queryEditor.object, queryModelService.object, connectionManagementService.object); + calledRunQueryStatementOnInput = false; + await queryAction.runCurrent(); + + //connection dialog should open and runQueryStatement should not be called + assert.equal(calledRunQueryStatementOnInput, false, 'runCurrent should not call runQueryStatement'); + testQueryInput.verify(x => x.runQueryStatement(TypeMoq.It.isAny()), TypeMoq.Times.never()); + connectionManagementService.verify(x => x.showConnectionDialog(TypeMoq.It.isAny()), TypeMoq.Times.once()); + + + // Calling runCurrent with an open connection + isConnected = true; + await queryAction.runCurrent(); + + //connection dialog should not open and runQueryStatement should be called + assert.equal(calledRunQueryStatementOnInput, true, 'runCurrent should call runQueryStatement'); + testQueryInput.verify(x => x.runQueryStatement(TypeMoq.It.isAny()), TypeMoq.Times.once()); + //show Dialog is not called + connectionManagementService.verify(x => x.showConnectionDialog(TypeMoq.It.isAny()), TypeMoq.Times.once()); + + // Calling runCurrent with empty Selection + isConnected = true; + calledRunQueryStatementOnInput = false; + await queryAction.runCurrent(); + + // Selection is empty + queryEditor.setup(x => x.isSelectionEmpty()).returns(() => true); + + //connection dialog should not open and runQueryStatement should not be called + assert.equal(calledRunQueryStatementOnInput, false, 'runCurrent should not call runQueryStatemet'); + connectionManagementService.verify(x => x.showConnectionDialog(TypeMoq.It.isAny()), TypeMoq.Times.once()); + }); + + test('runCurrent- calls appropriate run methods based on different selections', async () => { + // setting up environment + let calledRunQueryStatementOnInput: boolean = undefined; + let predefinedCursorSelection: IRange = { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 }; + let predefinedRangeSelection: IRange = { startLineNumber: 1, startColumn: 2, endLineNumber: 3, endColumn: 4 }; + + // mocking query editor + const contextkeyservice = new MockContextKeyService(); + let queryEditor = TypeMoq.Mock.ofType(QueryEditor, TypeMoq.MockBehavior.Loose, undefined, new TestThemeService(), + new TestStorageService(), contextkeyservice, undefined, new TestFileService(), undefined); + queryEditor.setup(x => x.input).returns(() => testQueryInput.object); + + // mocking isConnected in ConnectionManagementService + connectionManagementService.setup(x => x.isConnected(TypeMoq.It.isAnyString())).returns(() => true); + + // Mocking runQuery and runQueryStatement in unititledQueryEditorInput + testQueryInput.setup(x => x.runQuery(TypeMoq.It.isAny())).callback(() => { calledRunQueryOnInput = true; }); + testQueryInput.setup(x => x.runQueryStatement(TypeMoq.It.isAny())).callback(() => { calledRunQueryStatementOnInput = true; }); + + // mocking QueryModelService + let queryModelService = TypeMoq.Mock.ofType(QueryModelService, TypeMoq.MockBehavior.Loose); + queryModelService.setup(x => x.runQuery(TypeMoq.It.isAny(), undefined, TypeMoq.It.isAny())); + queryModelService.setup(x => x.runQueryStatement(TypeMoq.It.isAny(), TypeMoq.It.isAny())); + + let queryAction: RunQueryAction = new RunQueryAction(queryEditor.object, queryModelService.object, connectionManagementService.object); + + // setting up queryEditor with only a cursor. This case should call runQueryStatement + queryEditor.setup(x => x.getSelection(false)).returns(() => { return predefinedCursorSelection; }); + calledRunQueryOnInput = false; + calledRunQueryStatementOnInput = false; + await queryAction.runCurrent(); + + assert.equal(calledRunQueryStatementOnInput, true, 'runCurrent should call runQueryStatement'); + assert.equal(calledRunQueryOnInput, false, 'run should not call runQuery'); + + // checking if runQuery statement is called with predefinedCursorSelection only + testQueryInput.verify(x => x.runQueryStatement(TypeMoq.It.isValue(predefinedCursorSelection)), TypeMoq.Times.once()); + testQueryInput.verify(x => x.runQueryStatement(TypeMoq.It.isAny()), TypeMoq.Times.once()); + + // checking if runQuery is not called at all + testQueryInput.verify(x => x.runQuery(TypeMoq.It.isAny()), TypeMoq.Times.never()); + + // setting up queryEditor with a selection range. This case should call runQuery + queryEditor.setup(x => x.getSelection()).returns(() => { return predefinedRangeSelection; }); + queryEditor.setup(x => x.getSelection(false)).returns(() => { return predefinedRangeSelection; }); + + calledRunQueryOnInput = false; + calledRunQueryStatementOnInput = false; + await queryAction.runCurrent(); + + assert.equal(calledRunQueryStatementOnInput, false, 'runCurrent should not call runQueryStatement'); + assert.equal(calledRunQueryOnInput, true, 'run should call runQuery'); + + // checking if runQuery is called with predefinedRangeSelection only + testQueryInput.verify(x => x.runQuery(TypeMoq.It.isValue(predefinedRangeSelection)), TypeMoq.Times.once()); + testQueryInput.verify(x => x.runQuery(TypeMoq.It.isAny()), TypeMoq.Times.once()); + + // checking if runQueryStatement is never called + testQueryInput.verify(x => x.runQueryStatement(TypeMoq.It.isAny()), TypeMoq.Times.once()); + }); }); class ServiceAccessor {