move code from parts to contrib (#8319)

This commit is contained in:
Anthony Dresser
2019-11-14 12:23:11 -08:00
committed by GitHub
parent 6438967202
commit 7a2c30e159
619 changed files with 848 additions and 848 deletions

View File

@@ -0,0 +1,585 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Emitter } from 'vs/base/common/event';
import { ISelectionData } from 'azdata';
import {
IConnectionManagementService,
IConnectionParams,
INewConnectionParams,
ConnectionType,
RunQueryOnConnectionMode
} from 'sql/platform/connection/common/connectionManagement';
import { ConnectionDialogService } from 'sql/workbench/services/connection/browser/connectionDialogService';
import {
RunQueryAction, CancelQueryAction, ListDatabasesActionItem,
DisconnectDatabaseAction, ConnectDatabaseAction, QueryTaskbarAction
} from 'sql/workbench/contrib/query/browser/queryActions';
import { QueryInput } from 'sql/workbench/contrib/query/common/queryInput';
import { QueryEditor } from 'sql/workbench/contrib/query/browser/queryEditor';
import { QueryModelService } from 'sql/platform/query/common/queryModelService';
import { ConnectionManagementService } from 'sql/workbench/services/connection/browser/connectionManagementService';
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import * as TypeMoq from 'typemoq';
import * as assert from 'assert';
import { TestStorageService, TestFileService } from 'vs/workbench/test/workbenchTestServices';
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
let none: void;
suite('SQL QueryAction Tests', () => {
let testUri: string = 'testURI';
let editor: TypeMoq.Mock<QueryEditor>;
let calledRunQueryOnInput: boolean = undefined;
let testQueryInput: TypeMoq.Mock<QueryInput>;
let configurationService: TypeMoq.Mock<IConfigurationService>;
setup(() => {
// Setup a reusable mock QueryInput
testQueryInput = TypeMoq.Mock.ofType(QueryInput, TypeMoq.MockBehavior.Strict);
testQueryInput.setup(x => x.uri).returns(() => testUri);
testQueryInput.setup(x => x.runQuery(undefined)).callback(() => { calledRunQueryOnInput = true; });
const contextkeyservice = new MockContextKeyService();
// Setup a reusable mock QueryEditor
editor = TypeMoq.Mock.ofType(QueryEditor, TypeMoq.MockBehavior.Strict, undefined, new TestThemeService(),
new TestStorageService(), contextkeyservice, undefined, new TestFileService(), undefined);
editor.setup(x => x.input).returns(() => testQueryInput.object);
editor.setup(x => x.getSelection()).returns(() => undefined);
editor.setup(x => x.getSelection(false)).returns(() => undefined);
editor.setup(x => x.isSelectionEmpty()).returns(() => false);
configurationService = TypeMoq.Mock.ofInstance({
getValue: () => undefined,
onDidChangeConfiguration: () => undefined
} as any);
configurationService.setup(x => x.getValue(TypeMoq.It.isAny())).returns(() => {
return {};
});
});
test('setClass sets child CSS class correctly', (done) => {
// If I create a RunQueryAction
let queryAction: QueryTaskbarAction = new RunQueryAction(undefined, undefined, undefined);
// "class should automatically get set to include the base class and the RunQueryAction class
let className = RunQueryAction.EnabledClass;
assert.equal(queryAction.class, className, 'CSS class not properly set');
done();
});
test('getConnectedQueryEditorUri returns connected URI only if connected', (done) => {
// ... Create assert variables
let isConnectedReturnValue: boolean = false;
// ... Mock "isConnected in ConnectionManagementService
let connectionManagementService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, {}, {}, new TestStorageService());
connectionManagementService.setup(x => x.isConnected(TypeMoq.It.isAnyString())).returns(() => isConnectedReturnValue);
const contextkeyservice = new MockContextKeyService();
// Setup a reusable mock QueryEditor
editor = TypeMoq.Mock.ofType(QueryEditor, TypeMoq.MockBehavior.Strict, undefined, new TestThemeService(),
new TestStorageService(), contextkeyservice, undefined, new TestFileService(), undefined);
editor.setup(x => x.input).returns(() => testQueryInput.object);
// If I create a QueryTaskbarAction and I pass a non-connected editor to _getConnectedQueryEditorUri
let queryAction: QueryTaskbarAction = new RunQueryAction(undefined, undefined, connectionManagementService.object);
let connected: boolean = queryAction.isConnected(editor.object);
// I should get an unconnected state
assert(!connected, 'Non-connected editor should get back an undefined URI');
// If I run with a connected URI
isConnectedReturnValue = true;
connected = queryAction.isConnected(editor.object);
// I should get a connected state
assert(connected, 'Connected editor should get back a non-undefined URI');
done();
});
test('RunQueryAction calls runQuery() only if URI is connected', (done) => {
// ... Create assert variables
let isConnected: boolean = undefined;
let connectionParams: INewConnectionParams = undefined;
let countCalledShowDialog: number = 0;
// ... Mock "showDialog" ConnectionDialogService
let connectionDialogService = TypeMoq.Mock.ofType(ConnectionDialogService, TypeMoq.MockBehavior.Loose);
connectionDialogService.setup(x => x.showDialog(TypeMoq.It.isAny(), TypeMoq.It.isAny(), undefined, undefined, undefined))
.callback((service: IConnectionManagementService, params: INewConnectionParams) => {
connectionParams = params;
countCalledShowDialog++;
})
.returns(() => Promise.resolve(none));
// ... Mock "isConnected" in ConnectionManagementService
let connectionManagementService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, {}, undefined, connectionDialogService.object);
connectionManagementService.callBase = true;
connectionManagementService.setup(x => x.isConnected(TypeMoq.It.isAnyString())).returns(() => isConnected);
// ... Mock QueryModelService
let queryModelService = TypeMoq.Mock.ofType(QueryModelService, TypeMoq.MockBehavior.Loose);
queryModelService.setup(x => x.runQuery(TypeMoq.It.isAny(), undefined, TypeMoq.It.isAny(), TypeMoq.It.isAny()));
// If I call run on RunQueryAction when I am not connected
let queryAction: RunQueryAction = new RunQueryAction(editor.object, queryModelService.object, connectionManagementService.object);
isConnected = false;
calledRunQueryOnInput = false;
queryAction.run();
// runQuery should not be run
assert.equal(calledRunQueryOnInput, false, 'run should not call runQuery');
testQueryInput.verify(x => x.runQuery(undefined), TypeMoq.Times.never());
// and the connection dialog should open with the correct parameter details
assert.equal(countCalledShowDialog, 1, 'run should call showDialog');
assert.equal(connectionParams.connectionType, ConnectionType.editor, 'connectionType should be queryEditor');
assert.equal(connectionParams.runQueryOnCompletion, RunQueryOnConnectionMode.executeQuery, 'runQueryOnCompletion should be true`');
assert.equal(connectionParams.input.uri, testUri, 'URI should be set to the test URI');
assert.equal(connectionParams.input, editor.object.input, 'Editor should be set to the mock editor');
// If I call run on RunQueryAction when I am connected
isConnected = true;
queryAction.run();
//runQuery should be run, and the conneciton dialog should not open
assert.equal(calledRunQueryOnInput, true, 'run should call runQuery');
testQueryInput.verify(x => x.runQuery(undefined), TypeMoq.Times.once());
assert.equal(countCalledShowDialog, 1, 'run should not call showDialog');
done();
});
test('Queries are only run if the QueryEditor selection is not empty', (done) => {
// ... Create assert variables
let isSelectionEmpty: boolean = undefined;
let countCalledRunQuery: number = 0;
// ... Mock "isSelectionEmpty" in QueryEditor
let queryInput: TypeMoq.Mock<QueryInput> = TypeMoq.Mock.ofType(QueryInput, TypeMoq.MockBehavior.Strict);
queryInput = TypeMoq.Mock.ofType(QueryInput, TypeMoq.MockBehavior.Strict);
queryInput.setup(x => x.uri).returns(() => testUri);
queryInput.setup(x => x.runQuery(undefined)).callback(() => {
countCalledRunQuery++;
});
const contextkeyservice = new MockContextKeyService();
// Setup a reusable mock QueryEditor
let queryEditor = TypeMoq.Mock.ofType(QueryEditor, TypeMoq.MockBehavior.Strict, undefined, new TestThemeService(),
new TestStorageService(), contextkeyservice, undefined, new TestFileService(), undefined);
queryEditor.setup(x => x.input).returns(() => queryInput.object);
queryEditor.setup(x => x.getSelection()).returns(() => undefined);
queryEditor.setup(x => x.getSelection(false)).returns(() => undefined);
queryEditor.setup(x => x.isSelectionEmpty()).returns(() => isSelectionEmpty);
// ... Mock "isConnected" in ConnectionManagementService
let connectionManagementService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, {});
connectionManagementService.callBase = true;
connectionManagementService.setup(x => x.isConnected(TypeMoq.It.isAnyString())).returns(() => true);
// ... Mock QueryModelService
let queryModelService = TypeMoq.Mock.ofType(QueryModelService, TypeMoq.MockBehavior.Loose);
// If I call run on RunQueryAction when I have a non empty selection
let queryAction: RunQueryAction = new RunQueryAction(queryEditor.object, queryModelService.object, connectionManagementService.object);
isSelectionEmpty = false;
queryAction.run();
//runQuery should be run
assert.equal(countCalledRunQuery, 1, 'runQuery should be called');
// If I call run on RunQueryAction when I have an empty selection
isSelectionEmpty = true;
queryAction.run();
//runQuery should not be run again
assert.equal(countCalledRunQuery, 1, 'runQuery should not be called again');
done();
});
test('ISelectionData is properly passed when queries are run', () => {
/// Setup Test ///
// ... Create assert variables
let isConnected: boolean = undefined;
let countCalledShowDialog: number = 0;
let countCalledRunQuery: number = 0;
let showDialogConnectionParams: INewConnectionParams = undefined;
let runQuerySelection: ISelectionData = undefined;
let selectionToReturnInGetSelection: ISelectionData = undefined;
let predefinedSelection: ISelectionData = { startLine: 1, startColumn: 2, endLine: 3, endColumn: 4 };
// ... Mock "showDialog" ConnectionDialogService
let connectionDialogService = TypeMoq.Mock.ofType(ConnectionDialogService, TypeMoq.MockBehavior.Loose);
connectionDialogService.setup(x => x.showDialog(TypeMoq.It.isAny(), TypeMoq.It.isAny(), undefined, undefined, undefined))
.callback((service: IConnectionManagementService, params: INewConnectionParams) => {
showDialogConnectionParams = params;
countCalledShowDialog++;
})
.returns(() => Promise.resolve(none));
// ... Mock "getSelection" in QueryEditor
let queryInput = TypeMoq.Mock.ofType(QueryInput, TypeMoq.MockBehavior.Loose);
queryInput.setup(x => x.uri).returns(() => testUri);
queryInput.setup(x => x.runQuery(TypeMoq.It.isAny())).callback((selection: ISelectionData) => {
runQuerySelection = selection;
countCalledRunQuery++;
});
queryInput.setup(x => x.runQuery(undefined)).callback((selection: ISelectionData) => {
runQuerySelection = selection;
countCalledRunQuery++;
});
const contextkeyservice = new MockContextKeyService();
// Setup a reusable mock QueryEditor
let queryEditor = TypeMoq.Mock.ofType(QueryEditor, TypeMoq.MockBehavior.Strict, undefined, new TestThemeService(),
new TestStorageService(), contextkeyservice, undefined, new TestFileService(), undefined);
queryEditor.setup(x => x.input).returns(() => queryInput.object);
queryEditor.setup(x => x.isSelectionEmpty()).returns(() => false);
queryEditor.setup(x => x.getSelection()).returns(() => {
return selectionToReturnInGetSelection;
});
queryEditor.setup(x => x.getSelection(TypeMoq.It.isAny())).returns(() => {
return selectionToReturnInGetSelection;
});
// ... Mock "isConnected" in ConnectionManagementService
let connectionManagementService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, {}, undefined, connectionDialogService.object);
connectionManagementService.callBase = true;
connectionManagementService.setup(x => x.isConnected(TypeMoq.It.isAnyString())).returns(() => isConnected);
/// End Setup Test ///
////// If I call run on RunQueryAction while disconnected and with an undefined selection
let queryAction: RunQueryAction = new RunQueryAction(queryEditor.object, undefined, connectionManagementService.object);
isConnected = false;
selectionToReturnInGetSelection = undefined;
queryAction.run();
// The conneciton dialog should open with an undefined seleciton
assert.equal(countCalledShowDialog, 1, 'run should call showDialog');
assert.equal(countCalledRunQuery, 0, 'run should not call runQuery');
assert.equal(showDialogConnectionParams.connectionType, ConnectionType.editor, 'connectionType should be queryEditor');
assert.equal(showDialogConnectionParams.querySelection, undefined, 'querySelection should be undefined');
////// If I call run on RunQueryAction while disconnected and with a defined selection
isConnected = false;
selectionToReturnInGetSelection = predefinedSelection;
queryAction.run();
// The conneciton dialog should open with the correct seleciton
assert.equal(countCalledShowDialog, 2, 'run should call showDialog again');
assert.equal(countCalledRunQuery, 0, 'run should not call runQuery');
assert.equal(showDialogConnectionParams.connectionType, ConnectionType.editor, 'connectionType should be queryEditor');
assert.notEqual(showDialogConnectionParams.querySelection, undefined, 'There should not be an undefined selection in runQuery');
assert.equal(showDialogConnectionParams.querySelection.startLine, selectionToReturnInGetSelection.startLine, 'startLine should match');
assert.equal(showDialogConnectionParams.querySelection.startColumn, selectionToReturnInGetSelection.startColumn, 'startColumn should match');
assert.equal(showDialogConnectionParams.querySelection.endLine, selectionToReturnInGetSelection.endLine, 'endLine should match');
assert.equal(showDialogConnectionParams.querySelection.endColumn, selectionToReturnInGetSelection.endColumn, 'endColumn should match');
////// If I call run on RunQueryAction while connected and with an undefined selection
isConnected = true;
selectionToReturnInGetSelection = undefined;
queryAction.run();
// The query should run with an undefined selection
assert.equal(countCalledShowDialog, 2, 'run should not call showDialog');
assert.equal(countCalledRunQuery, 1, 'run should call runQuery');
assert.equal(runQuerySelection, undefined, 'There should be an undefined selection in runQuery');
////// If I call run on RunQueryAction while connected and with a defined selection
isConnected = true;
selectionToReturnInGetSelection = predefinedSelection;
queryAction.run();
// The query should run with the given seleciton
assert.equal(countCalledShowDialog, 2, 'run should not call showDialog');
assert.equal(countCalledRunQuery, 2, 'run should call runQuery again');
assert.notEqual(runQuerySelection, undefined, 'There should not be an undefined selection in runQuery');
assert.equal(runQuerySelection.startLine, selectionToReturnInGetSelection.startLine, 'startLine should match');
assert.equal(runQuerySelection.startColumn, selectionToReturnInGetSelection.startColumn, 'startColumn should match');
assert.equal(runQuerySelection.endLine, selectionToReturnInGetSelection.endLine, 'endLine should match');
assert.equal(runQuerySelection.endColumn, selectionToReturnInGetSelection.endColumn, 'endColumn should match');
});
test('CancelQueryAction calls cancelQuery() only if URI is connected', (done) => {
// ... Create assert variables
let isConnected: boolean = undefined;
let calledCancelQuery: boolean = false;
// ... Mock "isConnected" in ConnectionManagementService
let connectionManagementService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, {});
connectionManagementService.setup(x => x.isConnected(TypeMoq.It.isAnyString())).returns(() => isConnected);
// ... Mock QueryModelService
let queryModelService = TypeMoq.Mock.ofType(QueryModelService, TypeMoq.MockBehavior.Loose);
queryModelService.setup(x => x.cancelQuery(TypeMoq.It.isAny())).callback(() => {
calledCancelQuery = true;
});
// If I call run on CancelQueryAction when I am not connected
let queryAction: CancelQueryAction = new CancelQueryAction(editor.object, queryModelService.object, connectionManagementService.object);
isConnected = false;
queryAction.run();
// cancelQuery should not be run
assert.equal(calledCancelQuery, false, 'run should not call cancelQuery');
// If I call run on CancelQueryAction when I am connected
isConnected = true;
queryAction.run();
// cancelQuery should be run
assert.equal(calledCancelQuery, true, 'run should call cancelQuery');
done();
});
// We want to call disconnectEditor regardless of connection to be able to cancel in-progress connections
test('DisconnectDatabaseAction calls disconnectEditor regardless of URI being connected', (done) => {
// ... Create assert variables
let isConnected: boolean = undefined;
let countCalledDisconnectEditor: number = 0;
// ... Mock "isConnected" and "disconnectEditor" in ConnectionManagementService
let connectionManagementService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, {});
connectionManagementService.setup(x => x.isConnected(TypeMoq.It.isAnyString())).returns(() => isConnected);
connectionManagementService.setup(x => x.disconnectEditor(TypeMoq.It.isAny())).callback(() => {
countCalledDisconnectEditor++;
});
// If I call run on DisconnectDatabaseAction when I am not connected
let queryAction: DisconnectDatabaseAction = new DisconnectDatabaseAction(editor.object, connectionManagementService.object);
isConnected = false;
queryAction.run();
// disconnectEditor should be run
assert.equal(countCalledDisconnectEditor, 1, 'disconnectEditor should be called when URI is not connected');
// If I call run on DisconnectDatabaseAction when I am connected
isConnected = true;
queryAction.run();
// disconnectEditor should be run again
assert.equal(countCalledDisconnectEditor, 2, 'disconnectEditor should be called when URI is connected');
done();
});
test('ConnectDatabaseAction opens dialog regardless of URI connection state', (done) => {
// ... Create assert variables
let isConnected: boolean = undefined;
let connectionParams: INewConnectionParams = undefined;
let countCalledShowDialog: number = 0;
// ... Mock "showDialog" ConnectionDialogService
let connectionDialogService = TypeMoq.Mock.ofType(ConnectionDialogService, TypeMoq.MockBehavior.Loose);
connectionDialogService.setup(x => x.showDialog(TypeMoq.It.isAny(), TypeMoq.It.isAny(), undefined, undefined, undefined))
.callback((service: IConnectionManagementService, params: INewConnectionParams) => {
connectionParams = params;
countCalledShowDialog++;
})
.returns(() => Promise.resolve(none));
// ... Mock "isConnected" in ConnectionManagementService
let connectionManagementService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, {}, undefined, connectionDialogService.object);
connectionManagementService.callBase = true;
connectionManagementService.setup(x => x.isConnected(TypeMoq.It.isAnyString())).returns(() => isConnected);
// If I call run on ConnectDatabaseAction when I am not connected
let queryAction: ConnectDatabaseAction = new ConnectDatabaseAction(editor.object, false, connectionManagementService.object);
isConnected = false;
queryAction.run();
// The conneciton dialog should open with the correct parameter details
assert.equal(countCalledShowDialog, 1, 'run should call showDialog');
assert.equal(connectionParams.connectionType, ConnectionType.editor, 'connectionType should be queryEditor');
assert.equal(connectionParams.runQueryOnCompletion, false, 'runQueryOnCompletion should be false`');
assert.equal(connectionParams.input.uri, testUri, 'URI should be set to the test URI');
assert.equal(connectionParams.input, editor.object.input, 'Editor should be set to the mock editor');
// If I call run on ConnectDatabaseAction when I am connected
isConnected = true;
queryAction.run();
// The conneciton dialog should open again with the correct parameter details
assert.equal(countCalledShowDialog, 2, 'run should call showDialog');
assert.equal(connectionParams.connectionType, ConnectionType.editor, 'connectionType should be queryEditor');
assert.equal(connectionParams.runQueryOnCompletion, false, 'runQueryOnCompletion should be false`');
assert.equal(connectionParams.input.uri, testUri, 'URI should be set to the test URI');
assert.equal(connectionParams.input, editor.object.input, 'Editor should be set to the mock editor');
done();
});
test('ChangeConnectionAction connects regardless of URI being connected', (done) => {
// ... Create assert variables
let queryAction: ConnectDatabaseAction = undefined;
let isConnected: boolean = undefined;
let connectionParams: INewConnectionParams = undefined;
let calledShowDialog: number = 0;
// ... Mock "showDialog" ConnectionDialogService
let connectionDialogService = TypeMoq.Mock.ofType(ConnectionDialogService, TypeMoq.MockBehavior.Loose);
connectionDialogService.setup(x => x.showDialog(TypeMoq.It.isAny(), TypeMoq.It.isAny(), undefined, undefined, undefined))
.callback((service: IConnectionManagementService, params: INewConnectionParams) => {
calledShowDialog++;
connectionParams = params;
})
.returns(() => Promise.resolve(none));
// ... Mock "isConnected" in ConnectionManagementService
let connectionManagementService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, {}, undefined, connectionDialogService.object);
connectionManagementService.callBase = true;
connectionManagementService.setup(x => x.isConnected(TypeMoq.It.isAnyString())).returns(() => isConnected);
// If I call run on ChangeConnectionAction when I am not connected
queryAction = new ConnectDatabaseAction(editor.object, false, connectionManagementService.object);
isConnected = false;
queryAction.run();
// The connection dialog should open with the params set as below
assert.equal(calledShowDialog, 1, 'showDialog should be called when URI is connected');
assert.equal(connectionParams.connectionType, ConnectionType.editor, 'connectionType should be queryEditor');
assert.equal(connectionParams.runQueryOnCompletion, false, 'runQueryOnCompletion should be false`');
assert.equal(connectionParams.input.uri, testUri, 'URI should be set to the test URI');
assert.equal(connectionParams.input, editor.object.input, 'Editor should be set to the mock editor');
// Then if I call run on ChangeConnectionAction when I am connected
isConnected = true;
queryAction.run();
// The conneciton dialog should open with the params set as below
assert.equal(calledShowDialog, 2, 'showDialog should be called when URI is connected');
assert.equal(connectionParams.connectionType, ConnectionType.editor, 'connectionType should be queryEditor');
assert.equal(connectionParams.runQueryOnCompletion, false, 'runQueryOnCompletion should be false`');
assert.equal(connectionParams.input.uri, testUri, 'URI should be set to the test URI');
assert.equal(connectionParams.input, editor.object.input, 'Editor should be set to the mock editor');
done();
});
test('ListDatabaseItem shows items as expected', (done) => {
// ... Create assert variables
let listItem: ListDatabasesActionItem = undefined;
let isConnected: boolean = undefined;
let databaseName: string = undefined;
// ... Mock "isConnected" in ConnectionManagementService
let connectionManagementService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, {});
connectionManagementService.callBase = true;
connectionManagementService.setup(x => x.isConnected(TypeMoq.It.isAnyString())).returns(() => isConnected);
connectionManagementService.setup(x => x.getConnectionProfile(TypeMoq.It.isAny())).returns(() => <IConnectionProfile>{
databaseName: databaseName
});
// If I query without having initialized anything, state should be clear
listItem = new ListDatabasesActionItem(editor.object, undefined, connectionManagementService.object, undefined, configurationService.object);
assert.equal(listItem.isEnabled(), false, 'do not expect dropdown enabled unless connected');
assert.equal(listItem.currentDatabaseName, undefined, 'do not expect dropdown to have entries unless connected');
// When I connect, database name should be returned in the dropdown and this should be enabled
isConnected = true;
databaseName = 'master';
listItem.onConnected();
assert.equal(listItem.isEnabled(), true, 'expect dropdown enabled when connected');
assert.equal(listItem.currentDatabaseName, 'master', 'expect dropdown to have current DB name when connected');
// When I disconnect, state should return to default
isConnected = false;
databaseName = undefined;
listItem.onDisconnect();
assert.equal(listItem.isEnabled(), false, 'do not expect dropdown enabled unless connected');
assert.equal(listItem.currentDatabaseName, undefined, 'do not expect dropdown to have entries unless connected');
done();
});
test('ListDatabaseItem - null event params', () => {
// Setup:
// ... Create event emitter we can use to trigger db changed event
let dbChangedEmitter = new Emitter<IConnectionParams>();
// ... Create mock connection management service
let databaseName = 'foobar';
let cms = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, {});
cms.callBase = true;
cms.setup(x => x.onConnectionChanged).returns(() => dbChangedEmitter.event);
cms.setup(x => x.getConnectionProfile(TypeMoq.It.isAny())).returns(() => <IConnectionProfile>{ databaseName: databaseName });
// ... Create a database dropdown that has been connected
let listItem = new ListDatabasesActionItem(editor.object, undefined, cms.object, undefined, configurationService.object);
listItem.onConnected();
// If: I raise a connection changed event
let eventParams = null;
dbChangedEmitter.fire(eventParams);
// Then: The selected database should not have changed
assert.equal(listItem.currentDatabaseName, databaseName);
});
test('ListDatabaseItem - wrong uri', () => {
// Setup:
// ... Create event emitter we can use to trigger db changed event
let dbChangedEmitter = new Emitter<IConnectionParams>();
// ... Create mock connection management service that will not claim it's connected
let databaseName = 'foobar';
let cms = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, {}, {}, new TestStorageService());
cms.callBase = true;
cms.setup(x => x.onConnectionChanged).returns(() => dbChangedEmitter.event);
cms.setup(x => x.getConnectionProfile(TypeMoq.It.isAny())).returns(() => <IConnectionProfile>{ databaseName: databaseName });
// ... Create a database dropdown that has been connected
let listItem = new ListDatabasesActionItem(editor.object, undefined, cms.object, undefined, configurationService.object);
listItem.onConnected();
// If: I raise a connection changed event for the 'wrong' URI
let eventParams = <IConnectionParams>{
connectionProfile: {
databaseName: 'foobarbaz'
},
connectionUri: 'foobarUri'
};
dbChangedEmitter.fire(eventParams);
// Then: The selected database should not have changed
assert.equal(listItem.currentDatabaseName, databaseName);
});
test('ListDatabaseItem - updates when connected and uri matches', () => {
// Setup:
// ... Create event emitter we can use to trigger db changed event
let dbChangedEmitter = new Emitter<IConnectionParams>();
// ... Create mock connection management service
let cms = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, {}, {}, new TestStorageService());
cms.callBase = true;
cms.setup(x => x.onConnectionChanged).returns(() => dbChangedEmitter.event);
// ... Create a database dropdown
let listItem = new ListDatabasesActionItem(editor.object, undefined, cms.object, undefined, configurationService.object);
// If: I raise a connection changed event
let eventParams = <IConnectionParams>{
connectionProfile: {
databaseName: 'foobarbaz'
},
connectionUri: editor.object.input.uri
};
dbChangedEmitter.fire(eventParams);
// Then:
// ... The connection should have changed to the provided database
assert.equal(listItem.currentDatabaseName, eventParams.connectionProfile.databaseName);
});
});

View File

@@ -0,0 +1,327 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { IEditorDescriptor } from 'vs/workbench/browser/editor';
import { URI } from 'vs/base/common/uri';
import { Memento } from 'vs/workbench/common/memento';
import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput';
import { QueryResultsInput } from 'sql/workbench/contrib/query/common/queryResultsInput';
import { QueryModelService } from 'sql/platform/query/common/queryModelService';
import { QueryInput } from 'sql/workbench/contrib/query/common/queryInput';
import { INewConnectionParams, ConnectionType, RunQueryOnConnectionMode } from 'sql/platform/connection/common/connectionManagement';
import { ConnectionManagementService } from 'sql/workbench/services/connection/browser/connectionManagementService';
import { RunQueryAction, ListDatabasesActionItem } from 'sql/workbench/contrib/query/browser/queryActions';
import { EditorDescriptorService } from 'sql/workbench/services/queryEditor/browser/editorDescriptorService';
import * as TypeMoq from 'typemoq';
import * as assert from 'assert';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { TestStorageService } from 'vs/workbench/test/workbenchTestServices';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
suite('SQL QueryEditor Tests', () => {
let instantiationService: TypeMoq.Mock<InstantiationService>;
let editorDescriptorService: TypeMoq.Mock<EditorDescriptorService>;
let connectionManagementService: TypeMoq.Mock<ConnectionManagementService>;
let configurationService: TypeMoq.Mock<TestConfigurationService>;
let memento: TypeMoq.Mock<Memento>;
let mockEditor: any;
setup(() => {
// Create object to mock the Editor classes
// QueryResultsEditor fails at runtime due to the way we are importing Angualar,
// so a {} mock is used here. This mock simply needs to have empty method stubs
// for all called runtime methods
mockEditor = {
_bootstrapAngular: function () { },
setInput: function () { },
createEditor: function () { },
create: function () { },
setVisible: function () { },
layout: function () { },
dispose: function () { }
};
// Mock InstantiationService to give us our mockEditor
instantiationService = TypeMoq.Mock.ofType(InstantiationService, TypeMoq.MockBehavior.Loose);
instantiationService.setup(x => x.createInstance(TypeMoq.It.isAny())).returns((input) => {
return new Promise((resolve) => resolve(mockEditor));
});
instantiationService.setup(x => x.createInstance(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns((input) => {
return new Promise((resolve) => resolve(new RunQueryAction(undefined, undefined, undefined)));
});
// Setup hook to capture calls to create the listDatabase action
instantiationService.setup(x => x.createInstance(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns((classDef, editor, action) => {
if (classDef.ID) {
if (classDef.ID === 'listDatabaseQueryActionItem') {
return new ListDatabasesActionItem(editor, undefined, connectionManagementService.object, undefined, configurationService.object);
}
}
// Default
return new RunQueryAction(undefined, undefined, undefined);
});
// Mock EditorDescriptorService to give us a mock editor description
let descriptor: IEditorDescriptor = {
getId: function (): string { return 'id'; },
getName: function (): string { return 'name'; },
describes: function (obj: any): boolean { return true; },
instantiate(instantiationService: IInstantiationService): BaseEditor { return undefined; }
};
editorDescriptorService = TypeMoq.Mock.ofType(EditorDescriptorService, TypeMoq.MockBehavior.Loose);
editorDescriptorService.setup(x => x.getEditor(TypeMoq.It.isAny())).returns(() => descriptor);
configurationService = TypeMoq.Mock.ofInstance({
getValue: () => undefined,
onDidChangeConfiguration: () => undefined
} as any);
configurationService.setup(x => x.getValue(TypeMoq.It.isAny())).returns(() => {
return { enablePreviewFeatures: true };
});
// Mock ConnectionManagementService
memento = TypeMoq.Mock.ofType(Memento, TypeMoq.MockBehavior.Loose, '');
memento.setup(x => x.getMemento(TypeMoq.It.isAny())).returns(() => void 0);
connectionManagementService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, memento.object, undefined, new TestStorageService());
connectionManagementService.callBase = true;
connectionManagementService.setup(x => x.isConnected(TypeMoq.It.isAny())).returns(() => false);
connectionManagementService.setup(x => x.disconnectEditor(TypeMoq.It.isAny())).returns(() => void 0);
connectionManagementService.setup(x => x.ensureDefaultLanguageFlavor(TypeMoq.It.isAnyString())).returns(() => void 0);
});
/*
test('setInput creates SQL components', (done) => {
let assertInput = function () {
// The taskbar SQL, and parent should be created
assert.equal(!!editor.taskbar, true);
assert.equal(!!editor.taskbarContainer, true);
assert.equal(!!editor.getContainer(), true);
assert.equal(!!editor.sqlEditor, true);
assert.equal(!!editor.sqlEditorContainer, true);
// But the results componenets should not
assert.equal(!!editor.resultsEditor, false);
assert.equal(!!editor.resultsEditorContainer, false);
assert.equal(!!editor.sash, false);
assert.equal(!!editor._isResultsEditorVisible(), false);
};
// If I call create a QueryEditor
let editor: QueryEditor = getQueryEditor();
editor.create(parentBuilder);
return editor.setInput(queryInput) // Then I set the input
.then(assertInput) // Only the taskbar SQL, and parent should be created
.then(() => done(), (err) => done(err));
});
test('showQueryResultsEditor creates all components and pins editor', (done) => {
// Mock EditorGroupService to get call count of pinEditor
let editorGroupService = TypeMoq.Mock.ofType(TestEditorGroupService, TypeMoq.MockBehavior.Loose);
// Make the call to showQueryResultsEditor thenable
let showQueryResultsEditor = function () {
return editor._showQueryResultsEditor();
};
// Make the asserts thenable
let assertInput = function () {
assert.equal(!!editor.taskbar, true);
assert.equal(!!editor.taskbarContainer, true);
assert.equal(!!editor.getContainer(), true);
assert.equal(!!editor.sqlEditor, true);
assert.equal(!!editor.sqlEditorContainer, true);
assert.equal(!!editor.resultsEditor, true);
assert.equal(!!editor.resultsEditorContainer, true);
assert.equal(!!editor.sash, true);
assert.equal(!!editor._isResultsEditorVisible(), true);
editorGroupService.verify(x => x.pinEditor(undefined, TypeMoq.It.isAny()), TypeMoq.Times.once());
};
// If I create a QueryEditor
let editor: QueryEditor = new QueryEditor(
undefined,
themeService,
instantiationService.object,
undefined,
undefined,
undefined,
editorDescriptorService.object,
editorGroupService.object,
undefined,
undefined);
editor.create(parentBuilder);
return editor.setInput(queryInput) // Then I set the input
.then(showQueryResultsEditor) // Then call showQueryResultsEditor
.then(assertInput) // Both editor windows should be created, and the editor should be pinned
.then(() => done(), (err) => done(err));
});
test('Can switch between different input files', (done) => {
// Setup
let firstInput: EditorInput;
let firstContainer: HTMLElement;
let secondInput: EditorInput;
let secondContainer: HTMLElement;
const firstContainerId = 'firstContainerId';
const secondContainerId = 'secondContainerId';
let recordFirstInput = function () {
let input = <QueryInput>editor.input;
firstInput = input.sql;
firstContainer = editor.sqlEditorContainer;
firstContainer.id = firstContainerId;
};
let assertFirstInputIsSet = function () {
assert.notEqual(firstContainer.parentElement, undefined);
};
let setSecondInput = function () {
return editor.setInput(queryInput2);
};
let assertFirstInputIsRemoved = function () {
let input = <QueryInput>editor.input;
secondInput = input.sql;
secondContainer = editor.sqlEditorContainer;
secondContainer.id = secondContainerId;
// The inputs should not match
assert.notEqual(firstInput.getName(), secondInput.getName());
assert.notEqual(firstContainer.id, secondContainer.id);
assert.equal(firstContainer.id, firstContainerId);
// The first input should be disposed
assert.notEqual(firstContainer.parentElement, secondContainer.parentElement);
assert.equal(firstContainer.parentElement, undefined);
// The second input should be added into the DOM
assert.notEqual(secondContainer.parentElement, undefined);
};
let setFirstInputAgain = function () {
return editor.setInput(queryInput);
};
let assertFirstInputIsAddedBack = function () {
let input = <QueryInput>editor.input;
firstInput = input.sql;
firstContainer = editor.sqlEditorContainer;
// The inputs should not match
assert.notEqual(firstInput.getName(), secondInput.getName());
assert.notEqual(firstContainer.id, secondContainer.id);
assert.equal(secondContainer.id, secondContainerId);
// The first input should be added into the DOM
assert.equal(secondContainer.parentElement, undefined);
// The second input should be disposed
assert.notEqual(firstContainer.parentElement, secondContainer.parentElement);
assert.notEqual(firstContainer.parentElement, undefined);
};
// If I create a QueryEditor
let editor: QueryEditor = getQueryEditor();
editor.create(parentBuilder);
return editor.setInput(queryInput) // and I set the input
.then(recordFirstInput) // then I record what the input is
.then(assertFirstInputIsSet) // the input should be set
.then(setSecondInput) // then if I set the input to a new file
.then(assertFirstInputIsRemoved) // the inputs should not match, and the first input should be removed from the DOM
.then(setFirstInputAgain) // then if I set the input back to the original
.then(assertFirstInputIsAddedBack) // the inputs should not match, and the second input should be removed from the DOM
.then(() => done(), (err) => done(err));
});
*/
suite('Action Tests', () => {
let queryActionInstantiationService: TypeMoq.Mock<InstantiationService>;
let queryConnectionService: TypeMoq.Mock<ConnectionManagementService>;
let queryModelService: TypeMoq.Mock<QueryModelService>;
let queryInput: QueryInput;
setup(() => {
// Mock ConnectionManagementService but don't set connected state
memento = TypeMoq.Mock.ofType(Memento, TypeMoq.MockBehavior.Loose, '');
memento.setup(x => x.getMemento(TypeMoq.It.isAny())).returns(() => void 0);
queryConnectionService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, memento.object, undefined, new TestStorageService());
queryConnectionService.callBase = true;
queryConnectionService.setup(x => x.disconnectEditor(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => void 0);
queryConnectionService.setup(x => x.ensureDefaultLanguageFlavor(TypeMoq.It.isAnyString())).returns(() => void 0);
// Mock InstantiationService to give us the actions
queryActionInstantiationService = TypeMoq.Mock.ofType(InstantiationService, TypeMoq.MockBehavior.Loose);
queryActionInstantiationService.setup(x => x.createInstance(TypeMoq.It.isAny())).returns((input) => {
return new Promise((resolve) => resolve(mockEditor));
});
queryActionInstantiationService.setup(x => x.createInstance(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns((input) => {
// Default
return new RunQueryAction(undefined, undefined, undefined);
});
// Setup hook to capture calls to create the listDatabase action
queryActionInstantiationService.setup(x => x.createInstance(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()))
.returns((definition, editor, action, selectBox) => {
if (definition.ID === 'listDatabaseQueryActionItem') {
let item = new ListDatabasesActionItem(editor, undefined, queryConnectionService.object, undefined, configurationService.object);
return item;
}
// Default
return new RunQueryAction(undefined, undefined, undefined);
});
let fileInput = new UntitledEditorInput(URI.parse('file://testUri'), false, '', '', '', instantiationService.object, undefined, undefined);
queryModelService = TypeMoq.Mock.ofType(QueryModelService, TypeMoq.MockBehavior.Loose, undefined, undefined);
queryModelService.callBase = true;
queryModelService.setup(x => x.disposeQuery(TypeMoq.It.isAny())).returns(() => void 0);
queryInput = new QueryInput(
'',
fileInput,
undefined,
undefined,
connectionManagementService.object,
queryModelService.object,
undefined,
undefined
);
});
test('Taskbar buttons are set correctly upon standard load', () => {
queryConnectionService.setup(x => x.isConnected(TypeMoq.It.isAny())).returns(() => false);
queryModelService.setup(x => x.isRunningQuery(TypeMoq.It.isAny())).returns(() => false);
// If I use the created QueryEditor with no changes since creation
// Buttons should be set as if disconnected
assert.equal(queryInput.state.connected, false, 'query state should be not connected');
assert.equal(queryInput.state.executing, false, 'query state should be not executing');
assert.equal(queryInput.state.connecting, false, 'query state should be not connecting');
});
test('Taskbar buttons are set correctly upon connect', () => {
let params: INewConnectionParams = { connectionType: ConnectionType.editor, runQueryOnCompletion: RunQueryOnConnectionMode.none };
queryInput.onConnectSuccess(params);
queryModelService.setup(x => x.isRunningQuery(TypeMoq.It.isAny())).returns(() => false);
assert.equal(queryInput.state.connected, true, 'query state should be not connected');
assert.equal(queryInput.state.executing, false, 'query state should be not executing');
assert.equal(queryInput.state.connecting, false, 'query state should be not connecting');
});
test('Test that we attempt to dispose query when the queryInput is disposed', () => {
let queryResultsInput = new QueryResultsInput('testUri');
queryInput['_results'] = queryResultsInput;
queryInput.close();
queryModelService.verify(x => x.disposeQuery(TypeMoq.It.isAnyString()), TypeMoq.Times.once());
});
});
});