mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
SQL Operations Studio Public Preview 1 (0.23) release source code
This commit is contained in:
103
src/sqltest/common/telemetryUtilities.test.ts
Normal file
103
src/sqltest/common/telemetryUtilities.test.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
import * as TelemetryUtils from 'sql/common/telemetryUtilities';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { TelemetryServiceStub } from 'sqltest/stubs/telemetryServiceStub';
|
||||
import * as TypeMoq from 'typemoq';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import * as assert from 'assert';
|
||||
|
||||
suite('SQL Telemetry Utilities tests', () => {
|
||||
let telemetryService: TypeMoq.Mock<ITelemetryService>;
|
||||
let none: void;
|
||||
let providerName: string = 'provider name';
|
||||
let telemetryKey: string = 'tel key';
|
||||
|
||||
let connectionProfile = {
|
||||
databaseName: '',
|
||||
serverName: '',
|
||||
authenticationType: '',
|
||||
getOptionsKey: () => '',
|
||||
matches: undefined,
|
||||
groupFullName: '',
|
||||
groupId: '',
|
||||
id: '',
|
||||
options: {},
|
||||
password: '',
|
||||
providerName: providerName,
|
||||
savePassword: true,
|
||||
saveProfile: true,
|
||||
userName: ''
|
||||
};
|
||||
|
||||
setup(() => {
|
||||
telemetryService = TypeMoq.Mock.ofType(TelemetryServiceStub, TypeMoq.MockBehavior.Strict);
|
||||
telemetryService.setup(x => x.publicLog(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(x => TPromise.as(none));
|
||||
});
|
||||
|
||||
test('addTelemetry should add provider id using the connection', (done) => {
|
||||
let data: TelemetryUtils.IConnectionTelemetryData = {
|
||||
};
|
||||
|
||||
TelemetryUtils.addTelemetry(telemetryService.object, telemetryKey, data, connectionProfile).then(() => {
|
||||
telemetryService.verify(x => x.publicLog(TypeMoq.It.is(a => a === telemetryKey), TypeMoq.It.is(b => b.provider === providerName)), TypeMoq.Times.once());
|
||||
done();
|
||||
}).catch(err => {
|
||||
assert.fail(err);
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
test('addTelemetry should pass the telemetry data to telemetry service', (done) => {
|
||||
let data: TelemetryUtils.IConnectionTelemetryData = {
|
||||
target: 'target',
|
||||
from: 'from'
|
||||
};
|
||||
data.test1 = '1';
|
||||
|
||||
TelemetryUtils.addTelemetry(telemetryService.object, telemetryKey, data, connectionProfile).then(() => {
|
||||
telemetryService.verify(x => x.publicLog(
|
||||
TypeMoq.It.is(a => a === telemetryKey),
|
||||
TypeMoq.It.is(b => b.provider === providerName
|
||||
&& b.from === data.from
|
||||
&& b.target === data.target
|
||||
&& b.test1 === data.test1
|
||||
&& b.connection === undefined)), TypeMoq.Times.once());
|
||||
done();
|
||||
}).catch(err => {
|
||||
assert.fail(err);
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
test('addTelemetry should not crash not given data', (done) => {
|
||||
TelemetryUtils.addTelemetry(telemetryService.object, telemetryKey).then(() => {
|
||||
telemetryService.verify(x => x.publicLog(
|
||||
TypeMoq.It.is(a => a === telemetryKey),
|
||||
TypeMoq.It.is(b => b !== undefined)), TypeMoq.Times.once());
|
||||
done();
|
||||
}).catch(err => {
|
||||
assert.fail(err);
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
test('addTelemetry should try to get the provider name from data first', (done) => {
|
||||
let data: TelemetryUtils.IConnectionTelemetryData = {
|
||||
connection: connectionProfile
|
||||
};
|
||||
data.provider = providerName + '1';
|
||||
|
||||
TelemetryUtils.addTelemetry(telemetryService.object, telemetryKey, data, connectionProfile).then(() => {
|
||||
telemetryService.verify(x => x.publicLog(TypeMoq.It.is(a => a === telemetryKey), TypeMoq.It.is(b => b.provider === data.provider)), TypeMoq.Times.once());
|
||||
done();
|
||||
}).catch(err => {
|
||||
assert.fail(err);
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
191
src/sqltest/parts/accountManagement/accountActions.test.ts
Normal file
191
src/sqltest/parts/accountManagement/accountActions.test.ts
Normal file
@@ -0,0 +1,191 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as data from 'data';
|
||||
import * as TypeMoq from 'typemoq';
|
||||
import { AddAccountAction, RemoveAccountAction } from 'sql/parts/accountManagement/common/accountActions';
|
||||
import { AccountManagementTestService } from 'sqltest/stubs/accountManagementStubs';
|
||||
import { MessageServiceStub } from 'sqltest/stubs/messageServiceStub';
|
||||
import { ErrorMessageServiceStub } from 'sqltest/stubs/errorMessageServiceStub';
|
||||
|
||||
let testAccount = <data.Account>{
|
||||
key: {
|
||||
providerId: 'azure',
|
||||
accountId: 'testAccount'
|
||||
},
|
||||
displayInfo: {
|
||||
contextualLogo: { light: '', dark: '' },
|
||||
displayName: 'Test Account',
|
||||
contextualDisplayName: 'Azure Account'
|
||||
},
|
||||
isStale: false
|
||||
};
|
||||
|
||||
suite('Account Management Dialog Actions Tests', () => {
|
||||
test('AddAccount - Success', (done) => {
|
||||
// Setup: Create an AddAccountAction object
|
||||
let param = 'azure';
|
||||
let mocks = createAddAccountAction(true, true, param);
|
||||
|
||||
// If: I run the action when it will resolve
|
||||
mocks.action.run()
|
||||
.then(result => {
|
||||
// Then:
|
||||
// ... I should have gotten true back
|
||||
assert.ok(result);
|
||||
|
||||
// ... The account management service should have gotten a add account request
|
||||
mocks.accountMock.verify(x => x.addAccount(param), TypeMoq.Times.once());
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
err => done(err)
|
||||
);
|
||||
});
|
||||
|
||||
test('AddAccount - Failure', (done) => {
|
||||
// Setup: Create an AddAccountAction object
|
||||
let param = 'azure';
|
||||
let mocks = createAddAccountAction(false, true, param);
|
||||
|
||||
// If: I run the action when it will reject
|
||||
mocks.action.run().then(result => {
|
||||
// Then:
|
||||
// ... The result should be false since the operation failed
|
||||
assert.ok(!result);
|
||||
// ... The account management service should have gotten a add account request
|
||||
mocks.accountMock.verify(x => x.addAccount(param), TypeMoq.Times.once());
|
||||
done();
|
||||
}, error => {
|
||||
// Should fail as rejected actions cause the debugger to crash
|
||||
done(error);
|
||||
});
|
||||
});
|
||||
|
||||
test('RemoveAccount - Confirm Success', (done) => {
|
||||
// Setup: Create an AddAccountAction object
|
||||
let ams = getMockAccountManagementService(true);
|
||||
let ms = getMockMessageService(true);
|
||||
let es = getMockErrorMessageService();
|
||||
let action = new RemoveAccountAction(testAccount, ms.object, es.object, ams.object);
|
||||
|
||||
// If: I run the action when it will resolve
|
||||
action.run()
|
||||
.then(result => {
|
||||
// Then:
|
||||
// ... I should have gotten true back
|
||||
assert.ok(result);
|
||||
|
||||
// ... A confirmation dialog should have opened
|
||||
ms.verify(x => x.confirm(TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||
|
||||
// ... The account management service should have gotten a remove account request
|
||||
ams.verify(x => x.removeAccount(TypeMoq.It.isValue(testAccount.key)), TypeMoq.Times.once());
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
err => done(err)
|
||||
);
|
||||
});
|
||||
|
||||
test('RemoveAccount - Declined Success', (done) => {
|
||||
// Setup: Create an AddAccountAction object
|
||||
let ams = getMockAccountManagementService(true);
|
||||
let ms = getMockMessageService(false);
|
||||
let es = getMockErrorMessageService();
|
||||
let action = new RemoveAccountAction(testAccount, ms.object, es.object, ams.object);
|
||||
|
||||
// If: I run the action when it will resolve
|
||||
action.run()
|
||||
.then(result => {
|
||||
try {
|
||||
// Then:
|
||||
// ... I should have gotten false back
|
||||
assert.ok(!result);
|
||||
|
||||
// ... A confirmation dialog should have opened
|
||||
ms.verify(x => x.confirm(TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||
|
||||
// ... The account management service should not have gotten a remove account request
|
||||
ams.verify(x => x.removeAccount(TypeMoq.It.isAny()), TypeMoq.Times.never());
|
||||
|
||||
done();
|
||||
} catch (e) {
|
||||
done(e);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('RemoveAccount - Failure', (done) => {
|
||||
// Setup: Create an AddAccountAction object
|
||||
let ams = getMockAccountManagementService(false);
|
||||
let ms = getMockMessageService(true);
|
||||
let es = getMockErrorMessageService();
|
||||
let action = new RemoveAccountAction(testAccount, ms.object, es.object, ams.object);
|
||||
|
||||
// If: I run the action when it will reject
|
||||
action.run().then(result => {
|
||||
// Then:
|
||||
// ... The result should be false since the operation failed
|
||||
assert.ok(!result);
|
||||
// ... The account management service should have gotten a remove account request
|
||||
ams.verify(x => x.removeAccount(TypeMoq.It.isValue(testAccount.key)), TypeMoq.Times.once());
|
||||
done();
|
||||
}, error => {
|
||||
// Should fail as rejected actions cause the debugger to crash
|
||||
done(error);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function createAddAccountAction(resolve: boolean, confirm: boolean, param: string): IAddActionMocks {
|
||||
let ams = getMockAccountManagementService(resolve);
|
||||
let mockMessageService = getMockMessageService(confirm);
|
||||
let mockErrorMessageService = getMockErrorMessageService();
|
||||
return {
|
||||
accountMock: ams,
|
||||
messageMock: mockMessageService,
|
||||
errorMessageMock: mockErrorMessageService,
|
||||
action: new AddAccountAction(param, mockMessageService.object,
|
||||
mockErrorMessageService.object, ams.object)
|
||||
};
|
||||
}
|
||||
|
||||
function getMockAccountManagementService(resolve: boolean): TypeMoq.Mock<AccountManagementTestService> {
|
||||
let mockAccountManagementService = TypeMoq.Mock.ofType(AccountManagementTestService);
|
||||
|
||||
mockAccountManagementService.setup(x => x.addAccount(TypeMoq.It.isAnyString()))
|
||||
.returns(resolve ? () => Promise.resolve(null) : () => Promise.reject(null));
|
||||
mockAccountManagementService.setup(x => x.removeAccount(TypeMoq.It.isAny()))
|
||||
.returns(resolve ? () => Promise.resolve(true) : () => Promise.reject(null).then());
|
||||
|
||||
return mockAccountManagementService;
|
||||
}
|
||||
|
||||
function getMockMessageService(confirm: boolean): TypeMoq.Mock<MessageServiceStub> {
|
||||
let mockMessageService = TypeMoq.Mock.ofType(MessageServiceStub);
|
||||
|
||||
mockMessageService.setup(x => x.confirm(TypeMoq.It.isAny()))
|
||||
.returns(() => confirm);
|
||||
|
||||
return mockMessageService;
|
||||
}
|
||||
|
||||
function getMockErrorMessageService(): TypeMoq.Mock<ErrorMessageServiceStub> {
|
||||
let mockMessageService = TypeMoq.Mock.ofType(ErrorMessageServiceStub);
|
||||
mockMessageService.setup(x => x.showDialog(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()));
|
||||
return mockMessageService;
|
||||
}
|
||||
|
||||
interface IAddActionMocks
|
||||
{
|
||||
accountMock: TypeMoq.Mock<AccountManagementTestService>;
|
||||
messageMock: TypeMoq.Mock<MessageServiceStub>;
|
||||
errorMessageMock: TypeMoq.Mock<ErrorMessageServiceStub>;
|
||||
action: AddAccountAction;
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as TypeMoq from 'typemoq';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { AccountDialog } from 'sql/parts/accountManagement/accountDialog/accountDialog';
|
||||
import { AccountDialogController } from 'sql/parts/accountManagement/accountDialog/accountDialogController';
|
||||
import { AccountViewModel } from 'sql/parts/accountManagement/accountDialog/accountViewModel';
|
||||
import { AccountManagementTestService } from 'sqltest/stubs/accountManagementStubs';
|
||||
import { ErrorMessageServiceStub } from 'sqltest/stubs/errorMessageServiceStub';
|
||||
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
|
||||
import { AccountListRenderer } from 'sql/parts/accountManagement/common/accountListRenderer';
|
||||
import { ContextKeyServiceStub } from 'sqltest/stubs/contextKeyServiceStub';
|
||||
|
||||
// TESTS ///////////////////////////////////////////////////////////////////
|
||||
suite('Account Management Dialog Controller Tests', () => {
|
||||
test('Open Account Dialog - Dialog Doesn\'t Exist', () => {
|
||||
// Setup: Create instance of the controller
|
||||
let instantiationService = createInstantiationService();
|
||||
let controller = new AccountDialogController(instantiationService, undefined);
|
||||
assert.strictEqual(controller.accountDialog, undefined);
|
||||
|
||||
// If: I open the account dialog when one hasn't been opened
|
||||
controller.openAccountDialog();
|
||||
|
||||
// Then:
|
||||
// ... The account dialog should be defined
|
||||
assert.notStrictEqual(controller.accountDialog, undefined);
|
||||
});
|
||||
|
||||
test('Open Account Dialog - Dialog Exists', () => {
|
||||
// Setup: Create instance of the controller with an account dialog already loaded
|
||||
let instantiationService = createInstantiationService();
|
||||
let controller = new AccountDialogController(instantiationService, undefined);
|
||||
controller.openAccountDialog();
|
||||
let accountDialog = controller.accountDialog;
|
||||
|
||||
// If: I open the account dialog when one has already been opened
|
||||
controller.openAccountDialog();
|
||||
|
||||
// Then: It should be the same dialog that already existed
|
||||
assert.equal(controller.accountDialog, accountDialog);
|
||||
});
|
||||
|
||||
test('Add Account Failure - Error Message Shown', () => {
|
||||
// Setup:
|
||||
// ... Create instantiation service that returns mock emitter for account dialog
|
||||
let mockEventEmitter = new Emitter<string>();
|
||||
let instantiationService = createInstantiationService(mockEventEmitter);
|
||||
|
||||
// ... Create a mock instance of the error message service
|
||||
let errorMessageServiceStub = new ErrorMessageServiceStub();
|
||||
let mockErrorMessageService = TypeMoq.Mock.ofInstance(errorMessageServiceStub);
|
||||
mockErrorMessageService.setup(x => x.showDialog(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()));
|
||||
|
||||
// ... Create instance of the controller with an opened dialog
|
||||
let controller = new AccountDialogController(instantiationService, mockErrorMessageService.object);
|
||||
controller.openAccountDialog();
|
||||
|
||||
// If: The account dialog reports a failure adding an account
|
||||
mockEventEmitter.fire('Error message');
|
||||
|
||||
// Then: An error dialog should have been opened
|
||||
mockErrorMessageService.verify(x => x.showDialog(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||
});
|
||||
});
|
||||
|
||||
function createInstantiationService(addAccountFailureEmitter?: Emitter<string>): InstantiationService {
|
||||
// Create a mock account dialog view model
|
||||
let accountViewModel = new AccountViewModel(new AccountManagementTestService());
|
||||
let mockAccountViewModel = TypeMoq.Mock.ofInstance(accountViewModel);
|
||||
let mockEvent = new Emitter<any>();
|
||||
mockAccountViewModel.setup(x => x.addProviderEvent).returns(() => mockEvent.event);
|
||||
mockAccountViewModel.setup(x => x.removeProviderEvent).returns(() => mockEvent.event);
|
||||
mockAccountViewModel.setup(x => x.updateAccountListEvent).returns(() => mockEvent.event);
|
||||
|
||||
// Create a mocked out instantiation service
|
||||
let instantiationService = TypeMoq.Mock.ofType(InstantiationService, TypeMoq.MockBehavior.Strict);
|
||||
instantiationService.setup(x => x.createInstance<AccountViewModel>(TypeMoq.It.isValue(AccountViewModel)))
|
||||
.returns(() => mockAccountViewModel.object);
|
||||
instantiationService.setup(x => x.createInstance<AccountListRenderer>(TypeMoq.It.isValue(AccountListRenderer)))
|
||||
.returns(() => undefined);
|
||||
|
||||
// Create a mock account dialog
|
||||
let accountDialog = new AccountDialog(null, null, null, instantiationService.object, null, null, null, new ContextKeyServiceStub());
|
||||
let mockAccountDialog = TypeMoq.Mock.ofInstance(accountDialog);
|
||||
mockAccountDialog.setup(x => x.onAddAccountErrorEvent)
|
||||
.returns(() => { return addAccountFailureEmitter ? addAccountFailureEmitter.event : mockEvent.event; });
|
||||
mockAccountDialog.setup(x => x.onCloseEvent)
|
||||
.returns(() => mockEvent.event);
|
||||
mockAccountDialog.setup(x => x.render())
|
||||
.returns(() => undefined);
|
||||
mockAccountDialog.setup(x => x.open())
|
||||
.returns(() => undefined);
|
||||
instantiationService.setup(x => x.createInstance<AccountDialog>(TypeMoq.It.isValue(AccountDialog)))
|
||||
.returns(() => mockAccountDialog.object);
|
||||
|
||||
return instantiationService.object;
|
||||
}
|
||||
224
src/sqltest/parts/accountManagement/accountViewModel.test.ts
Normal file
224
src/sqltest/parts/accountManagement/accountViewModel.test.ts
Normal file
@@ -0,0 +1,224 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as data from 'data';
|
||||
import * as TypeMoq from 'typemoq';
|
||||
import { EventVerifierSingle } from 'sqltest/utils/eventVerifier';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { AccountViewModel } from 'sql/parts/accountManagement/accountDialog/accountViewModel';
|
||||
import { AccountProviderAddedEventParams, UpdateAccountListEventParams } from 'sql/services/accountManagement/eventTypes';
|
||||
import { AccountManagementTestService } from 'sqltest/stubs/accountManagementStubs';
|
||||
|
||||
// SUITE STATE /////////////////////////////////////////////////////////////
|
||||
let mockAddProviderEmitter: Emitter<AccountProviderAddedEventParams>;
|
||||
let mockRemoveProviderEmitter: Emitter<data.AccountProviderMetadata>;
|
||||
let mockUpdateAccountEmitter: Emitter<UpdateAccountListEventParams>;
|
||||
|
||||
let providers: data.AccountProviderMetadata[];
|
||||
let accounts: data.Account[];
|
||||
|
||||
suite('Account Management Dialog ViewModel Tests', () => {
|
||||
|
||||
suiteSetup(() => {
|
||||
providers = [{
|
||||
id: 'azure',
|
||||
displayName: 'Azure'
|
||||
}];
|
||||
|
||||
let account1 = {
|
||||
key: { providerId: 'azure', accountId: 'account1' },
|
||||
name: 'Account 1',
|
||||
displayInfo: {
|
||||
contextualDisplayName: 'Microsoft Account',
|
||||
contextualLogo: null,
|
||||
displayName: 'Account 1'
|
||||
},
|
||||
properties: [],
|
||||
isStale: false
|
||||
};
|
||||
let account2 = {
|
||||
key: { providerId: 'azure', accountId: 'account2' },
|
||||
name: 'Account 2',
|
||||
displayInfo: {
|
||||
contextualDisplayName: 'Work/School Account',
|
||||
contextualLogo: null,
|
||||
displayName: 'Account 2'
|
||||
},
|
||||
properties: [],
|
||||
isStale: true
|
||||
};
|
||||
accounts = [account1, account2];
|
||||
|
||||
// Setup event mocks for the account management service
|
||||
mockAddProviderEmitter = new Emitter<AccountProviderAddedEventParams>();
|
||||
mockRemoveProviderEmitter = new Emitter<data.AccountProviderMetadata>();
|
||||
mockUpdateAccountEmitter = new Emitter<UpdateAccountListEventParams>();
|
||||
});
|
||||
|
||||
test('Construction - Events are properly defined', () => {
|
||||
// If: I create an account viewmodel
|
||||
let mockAccountManagementService = getMockAccountManagementService(false, false);
|
||||
let vm = new AccountViewModel(mockAccountManagementService.object);
|
||||
|
||||
// Then:
|
||||
// ... All the events for the view models should be properly initialized
|
||||
assert.notEqual(vm.addProviderEvent, undefined);
|
||||
assert.notEqual(vm.removeProviderEvent, undefined);
|
||||
assert.notEqual(vm.updateAccountListEvent, undefined);
|
||||
|
||||
// ... All the events should properly fire
|
||||
let argAddProvider: AccountProviderAddedEventParams = { addedProvider: providers[0], initialAccounts: [] };
|
||||
let evAddProvider = new EventVerifierSingle<AccountProviderAddedEventParams>();
|
||||
vm.addProviderEvent(evAddProvider.eventHandler);
|
||||
mockAddProviderEmitter.fire(argAddProvider);
|
||||
evAddProvider.assertFired(argAddProvider);
|
||||
|
||||
let argRemoveProvider = providers[0];
|
||||
let evRemoveProvider = new EventVerifierSingle<data.AccountProviderMetadata>();
|
||||
vm.removeProviderEvent(evRemoveProvider.eventHandler);
|
||||
mockRemoveProviderEmitter.fire(argRemoveProvider);
|
||||
evRemoveProvider.assertFired(argRemoveProvider);
|
||||
|
||||
let argUpdateAccounts: UpdateAccountListEventParams = { providerId: providers[0].id, accountList: accounts };
|
||||
let evUpdateAccounts = new EventVerifierSingle<UpdateAccountListEventParams>();
|
||||
vm.updateAccountListEvent(evUpdateAccounts.eventHandler);
|
||||
mockUpdateAccountEmitter.fire(argUpdateAccounts);
|
||||
evUpdateAccounts.assertFired(argUpdateAccounts);
|
||||
});
|
||||
|
||||
test('Initialize - Success', done => {
|
||||
// Setup: Create a viewmodel with event handlers
|
||||
let mockAccountManagementService = getMockAccountManagementService(true, true);
|
||||
let evAddProvider = new EventVerifierSingle<AccountProviderAddedEventParams>();
|
||||
let evRemoveProvider = new EventVerifierSingle<data.AccountProviderMetadata>();
|
||||
let evUpdateAccounts = new EventVerifierSingle<UpdateAccountListEventParams>();
|
||||
let vm = getViewModel(mockAccountManagementService.object, evAddProvider, evRemoveProvider, evUpdateAccounts);
|
||||
|
||||
// If: I initialize the view model
|
||||
vm.initialize()
|
||||
.then(results => {
|
||||
// Then:
|
||||
// ... None of the events should have fired
|
||||
assertNoEventsFired(evAddProvider, evRemoveProvider, evUpdateAccounts);
|
||||
|
||||
// ... The account management service should have been called
|
||||
mockAccountManagementService.verify(x => x.getAccountProviderMetadata(), TypeMoq.Times.once());
|
||||
mockAccountManagementService.verify(x => x.getAccountsForProvider(TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||
|
||||
// ... The results that were returned should be an array of account provider added event params
|
||||
assert.ok(Array.isArray(results));
|
||||
assert.equal(results.length, 1);
|
||||
assert.equal(results[0].addedProvider, providers[0]);
|
||||
assert.equal(results[0].initialAccounts, accounts);
|
||||
}).then(
|
||||
() => done(),
|
||||
err => done(err)
|
||||
);
|
||||
});
|
||||
|
||||
test('Initialize - Get providers fails', done => {
|
||||
// Setup: Create a mock account management service that rejects looking up providers
|
||||
let mockAccountManagementService = getMockAccountManagementService(false, true);
|
||||
let evAddProvider = new EventVerifierSingle<AccountProviderAddedEventParams>();
|
||||
let evRemoveProvider = new EventVerifierSingle<data.AccountProviderMetadata>();
|
||||
let evUpdateAccounts = new EventVerifierSingle<UpdateAccountListEventParams>();
|
||||
let vm = getViewModel(mockAccountManagementService.object, evAddProvider, evRemoveProvider, evUpdateAccounts);
|
||||
|
||||
// If: I initialize the view model
|
||||
vm.initialize()
|
||||
.then(results => {
|
||||
// Then
|
||||
// ... None of the events should have fired
|
||||
assertNoEventsFired(evAddProvider, evRemoveProvider, evUpdateAccounts);
|
||||
|
||||
// ... The account management service should have been called for providers, but not accounts
|
||||
mockAccountManagementService.verify(x => x.getAccountProviderMetadata(), TypeMoq.Times.once());
|
||||
mockAccountManagementService.verify(x => x.getAccountsForProvider(TypeMoq.It.isAny()), TypeMoq.Times.never());
|
||||
|
||||
// ... The results that were returned should be an empty array
|
||||
assert.ok(Array.isArray(results));
|
||||
assert.equal(results.length, 0);
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
err => done(err)
|
||||
);
|
||||
});
|
||||
|
||||
test('Initialize - Get accounts fails', done => {
|
||||
// Setup: Create a mock account management service that rejects the promise
|
||||
let mockAccountManagementService = getMockAccountManagementService(true, false);
|
||||
let evAddProvider = new EventVerifierSingle<AccountProviderAddedEventParams>();
|
||||
let evRemoveProvider = new EventVerifierSingle<data.AccountProviderMetadata>();
|
||||
let evUpdateAccounts = new EventVerifierSingle<UpdateAccountListEventParams>();
|
||||
let vm = getViewModel(mockAccountManagementService.object, evAddProvider, evRemoveProvider, evUpdateAccounts);
|
||||
|
||||
// If: I initialize the view model
|
||||
vm.initialize()
|
||||
.then(result => {
|
||||
// Then:
|
||||
// ... None of the events should have fired
|
||||
assertNoEventsFired(evAddProvider, evRemoveProvider, evUpdateAccounts);
|
||||
|
||||
// ... The account management service should have been called
|
||||
mockAccountManagementService.verify(x => x.getAccountProviderMetadata(), TypeMoq.Times.once());
|
||||
mockAccountManagementService.verify(x => x.getAccountsForProvider(TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||
|
||||
// ... The results should include the provider
|
||||
assert.ok(Array.isArray(result));
|
||||
assert.equal(result.length, 1);
|
||||
assert.equal(result[0].addedProvider, providers[0]);
|
||||
assert.equal(result[0].initialAccounts, accounts);
|
||||
}).then(
|
||||
() => done(),
|
||||
err => done()
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
function getMockAccountManagementService(resolveProviders: boolean, resolveAccounts: boolean): TypeMoq.Mock<AccountManagementTestService> {
|
||||
let mockAccountManagementService = TypeMoq.Mock.ofType(AccountManagementTestService);
|
||||
|
||||
mockAccountManagementService.setup(x => x.getAccountProviderMetadata())
|
||||
.returns(() => resolveProviders ? Promise.resolve(providers) : Promise.reject(null).then());
|
||||
mockAccountManagementService.setup(x => x.getAccountsForProvider(TypeMoq.It.isAny()))
|
||||
.returns(() => resolveAccounts ? Promise.resolve(accounts) : Promise.reject(null).then());
|
||||
|
||||
mockAccountManagementService.setup(x => x.addAccountProviderEvent)
|
||||
.returns(() => mockAddProviderEmitter.event);
|
||||
mockAccountManagementService.setup(x => x.removeAccountProviderEvent)
|
||||
.returns(() => mockRemoveProviderEmitter.event);
|
||||
mockAccountManagementService.setup(x => x.updateAccountListEvent)
|
||||
.returns(() => mockUpdateAccountEmitter.event);
|
||||
|
||||
return mockAccountManagementService;
|
||||
}
|
||||
|
||||
function getViewModel(
|
||||
ams: AccountManagementTestService,
|
||||
evAdd: EventVerifierSingle<AccountProviderAddedEventParams>,
|
||||
evRemove: EventVerifierSingle<data.AccountProviderMetadata>,
|
||||
evUpdate: EventVerifierSingle<UpdateAccountListEventParams>
|
||||
): AccountViewModel {
|
||||
let vm = new AccountViewModel(ams);
|
||||
vm.addProviderEvent(evAdd.eventHandler);
|
||||
vm.removeProviderEvent(evRemove.eventHandler);
|
||||
vm.updateAccountListEvent(evUpdate.eventHandler);
|
||||
|
||||
return vm;
|
||||
}
|
||||
|
||||
function assertNoEventsFired(
|
||||
evAdd: EventVerifierSingle<AccountProviderAddedEventParams>,
|
||||
evRemove: EventVerifierSingle<data.AccountProviderMetadata>,
|
||||
evUpdate: EventVerifierSingle<UpdateAccountListEventParams>
|
||||
): void {
|
||||
evAdd.assertNotFired();
|
||||
evRemove.assertNotFired();
|
||||
evUpdate.assertNotFired();
|
||||
}
|
||||
30
src/sqltest/parts/admin/adminService.test.ts
Normal file
30
src/sqltest/parts/admin/adminService.test.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import data = require('data');
|
||||
import * as TypeMoq from 'typemoq';
|
||||
|
||||
import { AdminService } from 'sql/parts/admin/common/adminService';
|
||||
|
||||
suite('SQL AdminService tests', () => {
|
||||
|
||||
let adminService: AdminService;
|
||||
setup(() => {
|
||||
adminService = new AdminService(
|
||||
undefined, undefined, undefined, undefined
|
||||
);
|
||||
});
|
||||
|
||||
test('createDatabase should call tools service provider', done => {
|
||||
done();
|
||||
// adminService.createDatabase(undefined, undefined).then((result) => {
|
||||
// assert.notEqual(result, undefined, 'Result is undefined');
|
||||
// done();
|
||||
// });
|
||||
});
|
||||
});
|
||||
415
src/sqltest/parts/common/optionsDialogHelper.test.ts
Normal file
415
src/sqltest/parts/common/optionsDialogHelper.test.ts
Normal file
@@ -0,0 +1,415 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
import * as OptionsDialogHelper from 'sql/base/browser/ui/modal/optionsDialogHelper';
|
||||
import { ServiceOptionType } from 'sql/parts/connection/common/connectionManagement';
|
||||
import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox';
|
||||
import data = require('data');
|
||||
import { Builder, $ } from 'vs/base/browser/builder';
|
||||
import * as TypeMoq from 'typemoq';
|
||||
import * as assert from 'assert';
|
||||
|
||||
suite('Advanced options helper tests', () => {
|
||||
var possibleInputs: string[];
|
||||
let options: { [name: string]: any };
|
||||
var categoryOption: data.ServiceOption;
|
||||
var booleanOption: data.ServiceOption;
|
||||
var numberOption: data.ServiceOption;
|
||||
var stringOption: data.ServiceOption;
|
||||
var defaultGroupOption: data.ServiceOption;
|
||||
var isValid: boolean;
|
||||
var inputValue: string;
|
||||
var inputBox: TypeMoq.Mock<InputBox>;
|
||||
|
||||
var optionsMap: { [optionName: string]: OptionsDialogHelper.IOptionElement };
|
||||
|
||||
setup(() => {
|
||||
options = {};
|
||||
optionsMap = {};
|
||||
|
||||
categoryOption = {
|
||||
name: 'applicationIntent',
|
||||
displayName: 'Application Intent',
|
||||
description: 'Declares the application workload type when connecting to a server',
|
||||
groupName: 'Initialization',
|
||||
categoryValues: [
|
||||
{ displayName: 'ReadWrite', name: 'ReadWrite' },
|
||||
{ displayName: 'ReadOnly', name: 'ReadOnly' }
|
||||
],
|
||||
defaultValue: null,
|
||||
isRequired: false,
|
||||
valueType: ServiceOptionType.category,
|
||||
objectType: undefined,
|
||||
isArray: undefined
|
||||
};
|
||||
|
||||
booleanOption = {
|
||||
name: 'asynchronousProcessing',
|
||||
displayName: 'Asynchronous processing enabled',
|
||||
description: 'When true, enables usage of the Asynchronous functionality in the .Net Framework Data Provider',
|
||||
groupName: 'Initialization',
|
||||
categoryValues: null,
|
||||
defaultValue: null,
|
||||
isRequired: false,
|
||||
valueType: ServiceOptionType.boolean,
|
||||
objectType: undefined,
|
||||
isArray: undefined
|
||||
};
|
||||
|
||||
numberOption = {
|
||||
name: 'connectTimeout',
|
||||
displayName: 'Connect Timeout',
|
||||
description: 'The length of time (in seconds) to wait for a connection to the server before terminating the attempt and generating an error',
|
||||
groupName: 'Initialization',
|
||||
categoryValues: null,
|
||||
defaultValue: '15',
|
||||
isRequired: false,
|
||||
valueType: ServiceOptionType.number,
|
||||
objectType: undefined,
|
||||
isArray: undefined
|
||||
};
|
||||
|
||||
stringOption = {
|
||||
name: 'currentLanguage',
|
||||
displayName: 'Current Language',
|
||||
description: 'The SQL Server language record name',
|
||||
groupName: 'Initialization',
|
||||
categoryValues: null,
|
||||
defaultValue: null,
|
||||
isRequired: false,
|
||||
valueType: ServiceOptionType.string,
|
||||
objectType: undefined,
|
||||
isArray: undefined
|
||||
};
|
||||
|
||||
defaultGroupOption = {
|
||||
name: 'defaultGroupOption',
|
||||
displayName: 'Default Group',
|
||||
description: 'Test string option',
|
||||
groupName: undefined,
|
||||
categoryValues: null,
|
||||
defaultValue: null,
|
||||
isRequired: false,
|
||||
valueType: ServiceOptionType.string,
|
||||
objectType: undefined,
|
||||
isArray: undefined
|
||||
};
|
||||
|
||||
|
||||
let builder: Builder = $().div();
|
||||
inputBox = TypeMoq.Mock.ofType(InputBox, TypeMoq.MockBehavior.Loose, builder.getHTMLElement(), null, null);
|
||||
inputBox.callBase = true;
|
||||
inputBox.setup(x => x.validate()).returns(() => isValid);
|
||||
inputBox.setup(x => x.value).returns(() => inputValue);
|
||||
});
|
||||
|
||||
test('create default but not required category options should set the option value and possible inputs correctly', () => {
|
||||
categoryOption.defaultValue = 'ReadWrite';
|
||||
categoryOption.isRequired = false;
|
||||
possibleInputs = [];
|
||||
var optionValue = OptionsDialogHelper.getOptionValueAndCategoryValues(categoryOption, options, possibleInputs);
|
||||
assert.equal(optionValue, 'ReadWrite');
|
||||
assert.equal(possibleInputs.length, 3);
|
||||
assert.equal(possibleInputs[0], '');
|
||||
assert.equal(possibleInputs[1], 'ReadWrite');
|
||||
assert.equal(possibleInputs[2], 'ReadOnly');
|
||||
});
|
||||
|
||||
test('create default and required category options should set the option value and possible inputs correctly', () => {
|
||||
categoryOption.defaultValue = 'ReadWrite';
|
||||
categoryOption.isRequired = true;
|
||||
possibleInputs = [];
|
||||
var optionValue = OptionsDialogHelper.getOptionValueAndCategoryValues(categoryOption, options, possibleInputs);
|
||||
assert.equal(optionValue, 'ReadWrite');
|
||||
assert.equal(possibleInputs.length, 2);
|
||||
assert.equal(possibleInputs[0], 'ReadWrite');
|
||||
assert.equal(possibleInputs[1], 'ReadOnly');
|
||||
});
|
||||
|
||||
test('create no default and not required category options should set the option value and possible inputs correctly', () => {
|
||||
categoryOption.defaultValue = null;
|
||||
categoryOption.isRequired = false;
|
||||
possibleInputs = [];
|
||||
var optionValue = OptionsDialogHelper.getOptionValueAndCategoryValues(categoryOption, options, possibleInputs);
|
||||
assert.equal(optionValue, '');
|
||||
assert.equal(possibleInputs.length, 3);
|
||||
assert.equal(possibleInputs[0], '');
|
||||
assert.equal(possibleInputs[1], 'ReadWrite');
|
||||
assert.equal(possibleInputs[2], 'ReadOnly');
|
||||
});
|
||||
|
||||
test('create no default but required category options should set the option value and possible inputs correctly', () => {
|
||||
categoryOption.defaultValue = null;
|
||||
categoryOption.isRequired = true;
|
||||
possibleInputs = [];
|
||||
var optionValue = OptionsDialogHelper.getOptionValueAndCategoryValues(categoryOption, options, possibleInputs);
|
||||
assert.equal(optionValue, 'ReadWrite');
|
||||
assert.equal(possibleInputs.length, 2);
|
||||
assert.equal(possibleInputs[0], 'ReadWrite');
|
||||
assert.equal(possibleInputs[1], 'ReadOnly');
|
||||
});
|
||||
|
||||
test('create not required category options with option value should set the option value and possible inputs correctly', () => {
|
||||
categoryOption.defaultValue = null;
|
||||
categoryOption.isRequired = false;
|
||||
possibleInputs = [];
|
||||
options['applicationIntent'] = 'ReadOnly';
|
||||
var optionValue = OptionsDialogHelper.getOptionValueAndCategoryValues(categoryOption, options, possibleInputs);
|
||||
assert.equal(optionValue, 'ReadOnly');
|
||||
assert.equal(possibleInputs.length, 3);
|
||||
assert.equal(possibleInputs[0], '');
|
||||
assert.equal(possibleInputs[1], 'ReadWrite');
|
||||
assert.equal(possibleInputs[2], 'ReadOnly');
|
||||
});
|
||||
|
||||
test('create required category options with option value should set the option value and possible inputs correctly', () => {
|
||||
categoryOption.defaultValue = null;
|
||||
categoryOption.isRequired = true;
|
||||
possibleInputs = [];
|
||||
options['applicationIntent'] = 'ReadOnly';
|
||||
var optionValue = OptionsDialogHelper.getOptionValueAndCategoryValues(categoryOption, options, possibleInputs);
|
||||
assert.equal(optionValue, 'ReadOnly');
|
||||
assert.equal(possibleInputs.length, 2);
|
||||
assert.equal(possibleInputs[0], 'ReadWrite');
|
||||
assert.equal(possibleInputs[1], 'ReadOnly');
|
||||
});
|
||||
|
||||
test('create default but not required boolean options should set the option value and possible inputs correctly', () => {
|
||||
booleanOption.defaultValue = 'False';
|
||||
booleanOption.isRequired = false;
|
||||
possibleInputs = [];
|
||||
var optionValue = OptionsDialogHelper.getOptionValueAndCategoryValues(booleanOption, options, possibleInputs);
|
||||
assert.equal(optionValue, 'False');
|
||||
assert.equal(possibleInputs.length, 3);
|
||||
assert.equal(possibleInputs[0], '');
|
||||
assert.equal(possibleInputs[1], 'True');
|
||||
assert.equal(possibleInputs[2], 'False');
|
||||
});
|
||||
|
||||
test('create default and required boolean options should set the option value and possible inputs correctly', () => {
|
||||
booleanOption.defaultValue = 'False';
|
||||
booleanOption.isRequired = true;
|
||||
possibleInputs = [];
|
||||
var optionValue = OptionsDialogHelper.getOptionValueAndCategoryValues(booleanOption, options, possibleInputs);
|
||||
assert.equal(optionValue, 'False');
|
||||
assert.equal(possibleInputs.length, 2);
|
||||
assert.equal(possibleInputs[0], 'True');
|
||||
assert.equal(possibleInputs[1], 'False');
|
||||
});
|
||||
|
||||
test('create no default and not required boolean options should set the option value and possible inputs correctly', () => {
|
||||
booleanOption.defaultValue = null;
|
||||
booleanOption.isRequired = false;
|
||||
possibleInputs = [];
|
||||
var optionValue = OptionsDialogHelper.getOptionValueAndCategoryValues(booleanOption, options, possibleInputs);
|
||||
assert.equal(optionValue, '');
|
||||
assert.equal(possibleInputs.length, 3);
|
||||
assert.equal(possibleInputs[0], '');
|
||||
assert.equal(possibleInputs[1], 'True');
|
||||
assert.equal(possibleInputs[2], 'False');
|
||||
});
|
||||
|
||||
test('create no default but required boolean options should set the option value and possible inputs correctly', () => {
|
||||
booleanOption.defaultValue = null;
|
||||
booleanOption.isRequired = true;
|
||||
possibleInputs = [];
|
||||
var optionValue = OptionsDialogHelper.getOptionValueAndCategoryValues(booleanOption, options, possibleInputs);
|
||||
assert.equal(optionValue, 'True');
|
||||
assert.equal(possibleInputs.length, 2);
|
||||
assert.equal(possibleInputs[0], 'True');
|
||||
assert.equal(possibleInputs[1], 'False');
|
||||
});
|
||||
|
||||
test('create not required boolean options with option value should set the option value and possible inputs correctly', () => {
|
||||
booleanOption.defaultValue = null;
|
||||
booleanOption.isRequired = false;
|
||||
possibleInputs = [];
|
||||
options['asynchronousProcessing'] = true;
|
||||
var optionValue = OptionsDialogHelper.getOptionValueAndCategoryValues(booleanOption, options, possibleInputs);
|
||||
assert.equal(optionValue, 'True');
|
||||
assert.equal(possibleInputs.length, 3);
|
||||
assert.equal(possibleInputs[0], '');
|
||||
assert.equal(possibleInputs[1], 'True');
|
||||
assert.equal(possibleInputs[2], 'False');
|
||||
});
|
||||
|
||||
test('create required boolean options with option value should set the option value and possible inputs correctly', () => {
|
||||
booleanOption.defaultValue = null;
|
||||
booleanOption.isRequired = true;
|
||||
possibleInputs = [];
|
||||
options['asynchronousProcessing'] = 'False';
|
||||
var optionValue = OptionsDialogHelper.getOptionValueAndCategoryValues(booleanOption, options, possibleInputs);
|
||||
assert.equal(optionValue, 'False');
|
||||
assert.equal(possibleInputs.length, 2);
|
||||
assert.equal(possibleInputs[0], 'True');
|
||||
assert.equal(possibleInputs[1], 'False');
|
||||
});
|
||||
|
||||
test('create default number options should set the option value and possible inputs correctly', () => {
|
||||
numberOption.defaultValue = '15';
|
||||
numberOption.isRequired = true;
|
||||
possibleInputs = [];
|
||||
var optionValue = OptionsDialogHelper.getOptionValueAndCategoryValues(numberOption, options, possibleInputs);
|
||||
assert.equal(optionValue, '15');
|
||||
});
|
||||
|
||||
test('create number options with option value should set the option value and possible inputs correctly', () => {
|
||||
numberOption.defaultValue = '15';
|
||||
numberOption.isRequired = false;
|
||||
possibleInputs = [];
|
||||
options['connectTimeout'] = '45';
|
||||
var optionValue = OptionsDialogHelper.getOptionValueAndCategoryValues(numberOption, options, possibleInputs);
|
||||
assert.equal(optionValue, '45');
|
||||
});
|
||||
|
||||
test('create default string options should set the option value and possible inputs correctly', () => {
|
||||
stringOption.defaultValue = 'Japanese';
|
||||
stringOption.isRequired = true;
|
||||
possibleInputs = [];
|
||||
var optionValue = OptionsDialogHelper.getOptionValueAndCategoryValues(stringOption, options, possibleInputs);
|
||||
assert.equal(optionValue, 'Japanese');
|
||||
});
|
||||
|
||||
test('create string options with option value should set the option value and possible inputs correctly', () => {
|
||||
stringOption.defaultValue = 'Japanese';
|
||||
stringOption.isRequired = false;
|
||||
possibleInputs = [];
|
||||
options['currentLanguage'] = 'Spanish';
|
||||
var optionValue = OptionsDialogHelper.getOptionValueAndCategoryValues(stringOption, options, possibleInputs);
|
||||
assert.equal(optionValue, 'Spanish');
|
||||
});
|
||||
|
||||
test('validate undefined and optional number input should return no error', () => {
|
||||
isValid = true;
|
||||
inputValue = '';
|
||||
numberOption.isRequired = false;
|
||||
optionsMap = {};
|
||||
optionsMap['connectTimeout'] = {
|
||||
optionWidget: inputBox.object,
|
||||
option: numberOption,
|
||||
optionValue: null
|
||||
};
|
||||
|
||||
var error = OptionsDialogHelper.validateInputs(optionsMap);
|
||||
assert.equal(error, true);
|
||||
});
|
||||
|
||||
test('validate a valid optional number input should return no error', () => {
|
||||
isValid = true;
|
||||
inputValue = '30';
|
||||
numberOption.isRequired = false;
|
||||
optionsMap = {};
|
||||
optionsMap['connectTimeout'] = {
|
||||
optionWidget: inputBox.object,
|
||||
option: numberOption,
|
||||
optionValue: null
|
||||
};
|
||||
|
||||
var error = OptionsDialogHelper.validateInputs(optionsMap);
|
||||
assert.equal(error, true);
|
||||
});
|
||||
|
||||
test('validate a valid required number input should return no error', () => {
|
||||
isValid = true;
|
||||
inputValue = '30';
|
||||
numberOption.isRequired = true;
|
||||
optionsMap = {};
|
||||
optionsMap['connectTimeout'] = {
|
||||
optionWidget: inputBox.object,
|
||||
option: numberOption,
|
||||
optionValue: null
|
||||
};
|
||||
var error = OptionsDialogHelper.validateInputs(optionsMap);
|
||||
assert.equal(error, true);
|
||||
});
|
||||
|
||||
test('validate invalid optional number option should return an expected error', () => {
|
||||
isValid = false;
|
||||
inputValue = 'abc';
|
||||
numberOption.isRequired = false;
|
||||
optionsMap = {};
|
||||
optionsMap['connectTimeout'] = {
|
||||
optionWidget: inputBox.object,
|
||||
option: numberOption,
|
||||
optionValue: null
|
||||
};
|
||||
|
||||
var error = OptionsDialogHelper.validateInputs(optionsMap);
|
||||
assert.equal(error, false);
|
||||
});
|
||||
|
||||
test('validate required optional number option should return an expected error', () => {
|
||||
isValid = false;
|
||||
inputValue = '';
|
||||
numberOption.isRequired = true;
|
||||
optionsMap = {};
|
||||
optionsMap['connectTimeout'] = {
|
||||
optionWidget: inputBox.object,
|
||||
option: numberOption,
|
||||
optionValue: null
|
||||
};
|
||||
|
||||
var error = OptionsDialogHelper.validateInputs(optionsMap);
|
||||
assert.equal(error, false);
|
||||
});
|
||||
|
||||
test('update options should delete option entry if the input value is an empty string', () => {
|
||||
isValid = true;
|
||||
inputValue = '';
|
||||
numberOption.isRequired = false;
|
||||
optionsMap = {};
|
||||
optionsMap['connectTimeout'] = {
|
||||
optionWidget: inputBox.object,
|
||||
option: numberOption,
|
||||
optionValue: '45'
|
||||
};
|
||||
options['connectTimeout'] = '45';
|
||||
OptionsDialogHelper.updateOptions(options, optionsMap);
|
||||
assert.equal(options['connectTimeout'], undefined);
|
||||
});
|
||||
|
||||
test('update options should update correct option value', () => {
|
||||
isValid = true;
|
||||
inputValue = '50';
|
||||
numberOption.isRequired = false;
|
||||
optionsMap = {};
|
||||
optionsMap['connectTimeout'] = {
|
||||
optionWidget: inputBox.object,
|
||||
option: numberOption,
|
||||
optionValue: '45'
|
||||
};
|
||||
options['connectTimeout'] = '45';
|
||||
OptionsDialogHelper.updateOptions(options, optionsMap);
|
||||
assert.equal(options['connectTimeout'], 50);
|
||||
});
|
||||
|
||||
test('update options should add the option value to options', () => {
|
||||
isValid = true;
|
||||
inputValue = '50';
|
||||
numberOption.isRequired = false;
|
||||
optionsMap = {};
|
||||
optionsMap['connectTimeout'] = {
|
||||
optionWidget: inputBox.object,
|
||||
option: numberOption,
|
||||
optionValue: '45'
|
||||
};
|
||||
options = {};
|
||||
OptionsDialogHelper.updateOptions(options, optionsMap);
|
||||
assert.equal(options['connectTimeout'], 50);
|
||||
});
|
||||
|
||||
test('groupOptionsByCategory converts a list of options to a map of category names to lists of options', () => {
|
||||
let optionsList = [categoryOption, booleanOption, numberOption, stringOption, defaultGroupOption];
|
||||
let optionsMap = OptionsDialogHelper.groupOptionsByCategory(optionsList);
|
||||
let categoryNames = Object.keys(optionsMap);
|
||||
assert.equal(categoryNames.includes('Initialization'), true);
|
||||
assert.equal(categoryNames.includes('General'), true);
|
||||
assert.equal(categoryNames.length, 2);
|
||||
assert.equal(optionsMap['Initialization'].length, 4);
|
||||
assert.equal(optionsMap['General'].length, 1);
|
||||
});
|
||||
|
||||
});
|
||||
106
src/sqltest/parts/connection/advancedPropertiesDialog.test.ts
Normal file
106
src/sqltest/parts/connection/advancedPropertiesDialog.test.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
import { OptionsDialog } from 'sql/base/browser/ui/modal/optionsDialog';
|
||||
import { AdvancedPropertiesController } from 'sql/parts/connection/connectionDialog/advancedPropertiesController';
|
||||
import { Builder, $ } from 'vs/base/browser/builder';
|
||||
import { ContextKeyServiceStub } from 'sqltest/stubs/contextKeyServiceStub';
|
||||
import * as data from 'data';
|
||||
import * as TypeMoq from 'typemoq';
|
||||
import * as assert from 'assert';
|
||||
|
||||
suite('Advanced properties dialog tests', () => {
|
||||
var advancedController: AdvancedPropertiesController;
|
||||
var providerOptions: data.ConnectionOption[];
|
||||
|
||||
setup(() => {
|
||||
advancedController = new AdvancedPropertiesController(() => { }, null);
|
||||
providerOptions = [
|
||||
{
|
||||
name: 'a1',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: 'a',
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: null,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'b1',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: 'b',
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: null,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'noType',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: null,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'a2',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: 'a',
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: null,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'b2',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: 'b',
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: null,
|
||||
valueType: 0
|
||||
}
|
||||
];
|
||||
});
|
||||
|
||||
test('advanced dialog should open when showDialog in advancedController get called', () => {
|
||||
var isAdvancedDialogCalled = false;
|
||||
let options: { [name: string]: any } = {};
|
||||
let builder: Builder = $().div();
|
||||
let advanceDialog = TypeMoq.Mock.ofType(OptionsDialog, TypeMoq.MockBehavior.Strict,
|
||||
'', // title
|
||||
'', // name
|
||||
{}, // options
|
||||
undefined, // partsService
|
||||
undefined, // themeService
|
||||
undefined, // Context view service
|
||||
undefined, // telemetry service
|
||||
new ContextKeyServiceStub() // contextkeyservice
|
||||
);
|
||||
advanceDialog.setup(x => x.open(TypeMoq.It.isAny(), TypeMoq.It.isAny())).callback(() => {
|
||||
isAdvancedDialogCalled = true;
|
||||
});
|
||||
advancedController.advancedDialog = advanceDialog.object;
|
||||
advancedController.showDialog(providerOptions, builder.getHTMLElement(), options);
|
||||
assert.equal(isAdvancedDialogCalled, true);
|
||||
});
|
||||
});
|
||||
931
src/sqltest/parts/connection/connectionConfig.test.ts
Normal file
931
src/sqltest/parts/connection/connectionConfig.test.ts
Normal file
@@ -0,0 +1,931 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
|
||||
import * as TypeMoq from 'typemoq';
|
||||
import { ConnectionConfig, ISaveGroupResult } from 'sql/parts/connection/common/connectionConfig';
|
||||
import { IConnectionProfile, IConnectionProfileStore } from 'sql/parts/connection/common/interfaces';
|
||||
import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
|
||||
import { ConfigurationTarget, IConfigurationValue } from 'vs/workbench/services/configuration/common/configurationEditing';
|
||||
import { IConfigurationValue as TConfigurationValue } from 'vs/platform/configuration/common/configuration';
|
||||
import { WorkspaceConfigurationTestService } from 'sqltest/stubs/workspaceConfigurationTestService';
|
||||
import { ConfigurationEditingService } from 'vs/workbench/services/configuration/node/configurationEditingService';
|
||||
import * as Constants from 'sql/parts/connection/common/constants';
|
||||
import { IConnectionProfileGroup, ConnectionProfileGroup } from 'sql/parts/connection/common/connectionProfileGroup';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import * as assert from 'assert';
|
||||
import { CapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
|
||||
import data = require('data');
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
|
||||
suite('SQL ConnectionConfig tests', () => {
|
||||
let capabilitiesService: TypeMoq.Mock<CapabilitiesService>;
|
||||
let workspaceConfigurationServiceMock: TypeMoq.Mock<WorkspaceConfigurationTestService>;
|
||||
let configEditingServiceMock: TypeMoq.Mock<ConfigurationEditingService>;
|
||||
let msSQLCapabilities: data.DataProtocolServerCapabilities;
|
||||
let capabilities: data.DataProtocolServerCapabilities[];
|
||||
let onProviderRegistered = new Emitter<data.DataProtocolServerCapabilities>();
|
||||
|
||||
let configValueToConcat: TConfigurationValue<IConnectionProfileGroup[]> = {
|
||||
workspace: [{
|
||||
name: 'g1',
|
||||
id: 'g1',
|
||||
parentId: 'ROOT',
|
||||
color: 'pink',
|
||||
description: 'g1'
|
||||
},
|
||||
{
|
||||
name: 'g1-1',
|
||||
id: 'g1-1',
|
||||
parentId: 'g1',
|
||||
color: 'blue',
|
||||
description: 'g1-1'
|
||||
}
|
||||
],
|
||||
user: [{
|
||||
name: 'ROOT',
|
||||
id: 'ROOT',
|
||||
parentId: '',
|
||||
color: 'white',
|
||||
description: 'ROOT'
|
||||
}, {
|
||||
name: 'g2',
|
||||
id: 'g2',
|
||||
parentId: 'ROOT',
|
||||
color: 'green',
|
||||
description: 'g2'
|
||||
},
|
||||
{
|
||||
name: 'g2-1',
|
||||
id: 'g2-1',
|
||||
parentId: 'g2',
|
||||
color: 'yellow',
|
||||
description: 'g2'
|
||||
},
|
||||
{
|
||||
name: 'g3',
|
||||
id: 'g3',
|
||||
parentId: '',
|
||||
color: 'orange',
|
||||
description: 'g3'
|
||||
},
|
||||
{
|
||||
name: 'g3-1',
|
||||
id: 'g3-1',
|
||||
parentId: 'g3',
|
||||
color: 'purple',
|
||||
description: 'g3-1'
|
||||
}
|
||||
],
|
||||
value: [],
|
||||
default: [],
|
||||
folder: []
|
||||
};
|
||||
|
||||
let configValueToMerge: TConfigurationValue<IConnectionProfileGroup[]> = {
|
||||
workspace: [
|
||||
{
|
||||
name: 'g1',
|
||||
id: 'g1',
|
||||
parentId: '',
|
||||
color: 'pink',
|
||||
description: 'g1'
|
||||
},
|
||||
{
|
||||
name: 'g1-1',
|
||||
id: 'g1-1',
|
||||
parentId: 'g1',
|
||||
color: 'blue',
|
||||
description: 'g1-1'
|
||||
}
|
||||
],
|
||||
user: [
|
||||
{
|
||||
name: 'g2',
|
||||
id: 'g2',
|
||||
parentId: '',
|
||||
color: 'green',
|
||||
description: 'g2'
|
||||
},
|
||||
{
|
||||
name: 'g2-1',
|
||||
id: 'g2-1',
|
||||
parentId: 'g2',
|
||||
color: 'yellow',
|
||||
description: 'g2'
|
||||
},
|
||||
{
|
||||
name: 'g1',
|
||||
id: 'g1',
|
||||
parentId: '',
|
||||
color: 'pink',
|
||||
description: 'g1'
|
||||
},
|
||||
{
|
||||
name: 'g1-2',
|
||||
id: 'g1-2',
|
||||
parentId: 'g1',
|
||||
color: 'silver',
|
||||
description: 'g1-2'
|
||||
}],
|
||||
value: [],
|
||||
default: [],
|
||||
folder: []
|
||||
};
|
||||
|
||||
let connections: TConfigurationValue<IConnectionProfileStore[]> = {
|
||||
workspace: [{
|
||||
options: {
|
||||
serverName: 'server1',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: ''
|
||||
},
|
||||
providerName: 'MSSQL',
|
||||
groupId: 'test',
|
||||
savePassword: true,
|
||||
id: 'server1'
|
||||
}
|
||||
|
||||
|
||||
],
|
||||
user: [{
|
||||
options: {
|
||||
serverName: 'server2',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: ''
|
||||
},
|
||||
providerName: 'MSSQL',
|
||||
groupId: 'test',
|
||||
savePassword: true,
|
||||
id: 'server2'
|
||||
}, {
|
||||
options: {
|
||||
serverName: 'server3',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: ''
|
||||
},
|
||||
providerName: 'MSSQL',
|
||||
groupId: 'g3',
|
||||
savePassword: true,
|
||||
id: 'server3'
|
||||
}
|
||||
],
|
||||
value: [],
|
||||
default: [],
|
||||
folder: []
|
||||
};
|
||||
setup(() => {
|
||||
capabilitiesService = TypeMoq.Mock.ofType(CapabilitiesService);
|
||||
capabilities = [];
|
||||
let connectionProvider: data.ConnectionProviderOptions = {
|
||||
options: [
|
||||
{
|
||||
name: 'serverName',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 0,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'databaseName',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 1,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'userName',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 3,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'authenticationType',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 2,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'password',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 4,
|
||||
valueType: 0
|
||||
}
|
||||
]
|
||||
};
|
||||
msSQLCapabilities = {
|
||||
protocolVersion: '1',
|
||||
providerName: 'MSSQL',
|
||||
providerDisplayName: 'MSSQL',
|
||||
connectionProvider: connectionProvider,
|
||||
adminServicesProvider: undefined,
|
||||
features: undefined
|
||||
};
|
||||
capabilities.push(msSQLCapabilities);
|
||||
|
||||
capabilitiesService.setup(x => x.getCapabilities()).returns(() => capabilities);
|
||||
capabilitiesService.setup(x => x.onProviderRegisteredEvent).returns(() => onProviderRegistered.event);
|
||||
|
||||
workspaceConfigurationServiceMock = TypeMoq.Mock.ofType(WorkspaceConfigurationTestService);
|
||||
workspaceConfigurationServiceMock.setup(x => x.reloadConfiguration())
|
||||
.returns(() => TPromise.as<{}>({}));
|
||||
|
||||
configEditingServiceMock = TypeMoq.Mock.ofType(ConfigurationEditingService);
|
||||
let nothing: void;
|
||||
configEditingServiceMock.setup(x => x.writeConfiguration(ConfigurationTarget.USER, TypeMoq.It.isAny())).returns(() => TPromise.as<void>(nothing));
|
||||
configEditingServiceMock.setup(x => x.writeConfiguration(ConfigurationTarget.WORKSPACE, TypeMoq.It.isAny())).returns(() => TPromise.as<void>(nothing));
|
||||
});
|
||||
|
||||
function groupsAreEqual(groups1: IConnectionProfileGroup[], groups2: IConnectionProfileGroup[]): Boolean {
|
||||
if (!groups1 && !groups2) {
|
||||
return true;
|
||||
} else if ((!groups1 && groups2 && groups2.length === 0) || (!groups2 && groups1 && groups1.length === 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (groups1.length !== groups2.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let areEqual = true;
|
||||
|
||||
groups1.map(g1 => {
|
||||
if (areEqual) {
|
||||
let g2 = groups2.find(g => g.name === g1.name);
|
||||
if (!g2) {
|
||||
areEqual = false;
|
||||
} else {
|
||||
let result = groupsAreEqual(groups1.filter(a => a.parentId === g1.id), groups2.filter(b => b.parentId === g2.id));
|
||||
if (result === false) {
|
||||
areEqual = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return areEqual;
|
||||
}
|
||||
|
||||
test('allGroups should return groups from user and workspace settings', () => {
|
||||
workspaceConfigurationServiceMock.setup(x => x.lookup<IConnectionProfile[] | IConnectionProfileGroup[] | data.DataProtocolServerCapabilities[]>(
|
||||
Constants.connectionGroupsArrayName))
|
||||
.returns(() => configValueToConcat);
|
||||
|
||||
let config = new ConnectionConfig(configEditingServiceMock.object, workspaceConfigurationServiceMock.object, capabilitiesService.object);
|
||||
let allGroups = config.getAllGroups();
|
||||
|
||||
|
||||
assert.notEqual(allGroups, undefined);
|
||||
assert.equal(allGroups.length, configValueToConcat.workspace.length + configValueToConcat.user.length);
|
||||
});
|
||||
|
||||
test('allGroups should merge groups from user and workspace settings', () => {
|
||||
let expectedAllGroups: IConnectionProfileGroup[] = [
|
||||
{
|
||||
name: 'g1',
|
||||
id: 'g1',
|
||||
parentId: '',
|
||||
color: 'pink',
|
||||
description: 'g1'
|
||||
},
|
||||
{
|
||||
name: 'g1-1',
|
||||
id: 'g1-1',
|
||||
parentId: 'g1',
|
||||
color: 'blue',
|
||||
description: 'g1-1'
|
||||
},
|
||||
{
|
||||
name: 'g2',
|
||||
id: 'g2',
|
||||
parentId: '',
|
||||
color: 'yellow',
|
||||
description: 'g2'
|
||||
},
|
||||
{
|
||||
name: 'g2-1',
|
||||
id: 'g2-1',
|
||||
parentId: 'g2',
|
||||
color: 'red',
|
||||
description: 'g2'
|
||||
},
|
||||
{
|
||||
name: 'g1-2',
|
||||
id: 'g1-2',
|
||||
parentId: 'g1',
|
||||
color: 'green',
|
||||
description: 'g1-2'
|
||||
}];
|
||||
|
||||
workspaceConfigurationServiceMock.setup(x => x.lookup<IConnectionProfileStore[] | IConnectionProfileGroup[] | data.DataProtocolServerCapabilities[]>(
|
||||
Constants.connectionGroupsArrayName))
|
||||
.returns(() => configValueToMerge);
|
||||
|
||||
let config = new ConnectionConfig(configEditingServiceMock.object, workspaceConfigurationServiceMock.object, capabilitiesService.object);
|
||||
let allGroups = config.getAllGroups();
|
||||
|
||||
|
||||
assert.notEqual(allGroups, undefined);
|
||||
assert.equal(groupsAreEqual(allGroups, expectedAllGroups), true);
|
||||
});
|
||||
|
||||
test('addConnection should add the new profile to user settings if does not exist', done => {
|
||||
let newProfile: IConnectionProfile = {
|
||||
serverName: 'new server',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: undefined,
|
||||
groupId: undefined,
|
||||
getOptionsKey: undefined,
|
||||
matches: undefined,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: undefined
|
||||
};
|
||||
|
||||
let expectedNumberOfConnections = connections.user.length + 1;
|
||||
|
||||
workspaceConfigurationServiceMock.setup(x => x.lookup<IConnectionProfileStore[] | IConnectionProfileGroup[] | data.DataProtocolServerCapabilities[]>(
|
||||
Constants.connectionsArrayName))
|
||||
.returns(() => connections);
|
||||
workspaceConfigurationServiceMock.setup(x => x.lookup<IConnectionProfileStore[] | IConnectionProfileGroup[] | data.DataProtocolServerCapabilities[]>(
|
||||
Constants.connectionGroupsArrayName))
|
||||
.returns(() => configValueToConcat);
|
||||
|
||||
let connectionProfile = new ConnectionProfile(msSQLCapabilities, newProfile);
|
||||
connectionProfile.options['databaseDisplayName'] = 'database';
|
||||
let config = new ConnectionConfig(configEditingServiceMock.object, workspaceConfigurationServiceMock.object, capabilitiesService.object);
|
||||
config.addConnection(connectionProfile).then(savedConnectionProfile => {
|
||||
configEditingServiceMock.verify(y => y.writeConfiguration(ConfigurationTarget.USER,
|
||||
TypeMoq.It.is<IConfigurationValue>(c => (c.value as IConnectionProfileStore[]).length === expectedNumberOfConnections)), TypeMoq.Times.once());
|
||||
assert.notEqual(savedConnectionProfile.id, undefined);
|
||||
done();
|
||||
}).catch(error => {
|
||||
assert.fail();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('addConnection should not add the new profile to user settings if already exists', done => {
|
||||
let profileFromConfig = connections.user[0];
|
||||
let newProfile: IConnectionProfile = {
|
||||
serverName: profileFromConfig.options['serverName'],
|
||||
databaseName: profileFromConfig.options['databaseName'],
|
||||
userName: profileFromConfig.options['userName'],
|
||||
password: profileFromConfig.options['password'],
|
||||
authenticationType: profileFromConfig.options['authenticationType'],
|
||||
groupId: profileFromConfig.groupId,
|
||||
savePassword: true,
|
||||
groupFullName: undefined,
|
||||
getOptionsKey: undefined,
|
||||
matches: undefined,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: undefined
|
||||
};
|
||||
|
||||
let expectedNumberOfConnections = connections.user.length;
|
||||
|
||||
workspaceConfigurationServiceMock.setup(x => x.lookup<IConnectionProfileStore[] | IConnectionProfileGroup[] | data.DataProtocolServerCapabilities[]>(
|
||||
Constants.connectionsArrayName))
|
||||
.returns(() => connections);
|
||||
workspaceConfigurationServiceMock.setup(x => x.lookup<IConnectionProfileStore[] | IConnectionProfileGroup[] | data.DataProtocolServerCapabilities[]>(
|
||||
Constants.connectionGroupsArrayName))
|
||||
.returns(() => configValueToConcat);
|
||||
|
||||
let connectionProfile = new ConnectionProfile(msSQLCapabilities, newProfile);
|
||||
connectionProfile.options['databaseDisplayName'] = profileFromConfig.options['databaseName'];
|
||||
|
||||
let config = new ConnectionConfig(configEditingServiceMock.object, workspaceConfigurationServiceMock.object, capabilitiesService.object);
|
||||
config.addConnection(connectionProfile).then(savedConnectionProfile => {
|
||||
configEditingServiceMock.verify(y => y.writeConfiguration(ConfigurationTarget.USER,
|
||||
TypeMoq.It.is<IConfigurationValue>(c => (c.value as IConnectionProfileStore[]).length === expectedNumberOfConnections)), TypeMoq.Times.once());
|
||||
assert.equal(savedConnectionProfile.id, profileFromConfig.id);
|
||||
done();
|
||||
}).catch(error => {
|
||||
assert.fail();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('addConnection should add the new group to user settings if does not exist', done => {
|
||||
let newProfile: IConnectionProfile = {
|
||||
serverName: 'new server',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g2/g2-2',
|
||||
groupId: undefined,
|
||||
getOptionsKey: undefined,
|
||||
matches: undefined,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: undefined
|
||||
};
|
||||
|
||||
let expectedNumberOfConnections = connections.user.length + 1;
|
||||
let expectedNumberOfGroups = configValueToConcat.user.length + 1;
|
||||
|
||||
workspaceConfigurationServiceMock.setup(x => x.lookup<IConnectionProfileStore[] | IConnectionProfileGroup[] | data.DataProtocolServerCapabilities[]>(
|
||||
Constants.connectionsArrayName))
|
||||
.returns(() => connections);
|
||||
|
||||
workspaceConfigurationServiceMock.setup(x => x.lookup<IConnectionProfileStore[] | IConnectionProfileGroup[] | data.DataProtocolServerCapabilities[]>(
|
||||
Constants.connectionGroupsArrayName))
|
||||
.returns(() => configValueToConcat);
|
||||
|
||||
let connectionProfile = new ConnectionProfile(msSQLCapabilities, newProfile);
|
||||
let config = new ConnectionConfig(configEditingServiceMock.object, workspaceConfigurationServiceMock.object, capabilitiesService.object);
|
||||
config.addConnection(connectionProfile).then(success => {
|
||||
configEditingServiceMock.verify(y => y.writeConfiguration(ConfigurationTarget.USER,
|
||||
TypeMoq.It.is<IConfigurationValue>(c => (c.value as IConnectionProfileStore[]).length === expectedNumberOfConnections)), TypeMoq.Times.once());
|
||||
configEditingServiceMock.verify(y => y.writeConfiguration(ConfigurationTarget.USER,
|
||||
TypeMoq.It.is<IConfigurationValue>(c => (c.value as IConnectionProfileGroup[]).length === expectedNumberOfGroups)), TypeMoq.Times.once());
|
||||
done();
|
||||
}).catch(error => {
|
||||
assert.fail();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('getConnections should return connections from user and workspace settings given getWorkspaceConnections set to true', () => {
|
||||
let getWorkspaceConnections: boolean = true;
|
||||
|
||||
workspaceConfigurationServiceMock.setup(x => x.lookup<IConnectionProfileStore[] | IConnectionProfileGroup[] | data.DataProtocolServerCapabilities[]>(
|
||||
Constants.connectionsArrayName))
|
||||
.returns(() => connections);
|
||||
|
||||
let config = new ConnectionConfig(configEditingServiceMock.object, workspaceConfigurationServiceMock.object, capabilitiesService.object);
|
||||
let allConnections = config.getConnections(getWorkspaceConnections);
|
||||
assert.equal(allConnections.length, connections.user.length + connections.workspace.length);
|
||||
});
|
||||
|
||||
test('getConnections should return connections from user settings given getWorkspaceConnections set to false', () => {
|
||||
let getWorkspaceConnections: boolean = false;
|
||||
|
||||
workspaceConfigurationServiceMock.setup(x => x.lookup<IConnectionProfileStore[] | IConnectionProfileGroup[] | data.DataProtocolServerCapabilities[]>(
|
||||
Constants.connectionsArrayName))
|
||||
.returns(() => connections);
|
||||
|
||||
let config = new ConnectionConfig(configEditingServiceMock.object, workspaceConfigurationServiceMock.object, capabilitiesService.object);
|
||||
let allConnections = config.getConnections(getWorkspaceConnections);
|
||||
assert.equal(allConnections.length, connections.user.length);
|
||||
});
|
||||
|
||||
test('getConnections should return connections with a valid id', () => {
|
||||
let getWorkspaceConnections: boolean = false;
|
||||
let connectionsWithNoId: TConfigurationValue<IConnectionProfileStore[]> = {
|
||||
user: connections.user.map(c => {
|
||||
c.id = undefined;
|
||||
return c;
|
||||
}),
|
||||
default: connections.default,
|
||||
workspace: connections.workspace.map(c => {
|
||||
c.id = c.options['serverName'];
|
||||
return c;
|
||||
}),
|
||||
value: connections.value,
|
||||
folder: []
|
||||
};
|
||||
workspaceConfigurationServiceMock.setup(x => x.lookup<IConnectionProfileStore[] | IConnectionProfileGroup[] | data.DataProtocolServerCapabilities[]>(
|
||||
Constants.connectionsArrayName))
|
||||
.returns(() => connectionsWithNoId);
|
||||
|
||||
let config = new ConnectionConfig(configEditingServiceMock.object, workspaceConfigurationServiceMock.object, capabilitiesService.object);
|
||||
let allConnections = config.getConnections(getWorkspaceConnections);
|
||||
assert.equal(allConnections.length, connections.user.length);
|
||||
allConnections.forEach(connection => {
|
||||
let userConnection = connectionsWithNoId.user.find(u => u.options['serverName'] === connection.serverName);
|
||||
if (userConnection !== undefined) {
|
||||
assert.notEqual(connection.id, connection.getOptionsKey());
|
||||
assert.notEqual(connection.id, undefined);
|
||||
} else {
|
||||
let workspaceConnection = connectionsWithNoId.workspace.find(u => u.options['serverName'] === connection.serverName);
|
||||
assert.notEqual(connection.id, connection.getOptionsKey());
|
||||
assert.equal(workspaceConnection.id, connection.id);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('getConnections update the capabilities in each profile when the provider capabilities is registered', () => {
|
||||
let oldOptionName: string = 'oldOptionName';
|
||||
let optionsMetadataFromConfig = capabilities[0].connectionProvider.options.concat({
|
||||
name: oldOptionName,
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 0,
|
||||
valueType: 0
|
||||
});
|
||||
|
||||
let capabilitiesFromConfig: data.DataProtocolServerCapabilities[] = [];
|
||||
let connectionProvider: data.ConnectionProviderOptions = {
|
||||
options: optionsMetadataFromConfig
|
||||
};
|
||||
let msSQLCapabilities2 = {
|
||||
protocolVersion: '1',
|
||||
providerName: 'MSSQL',
|
||||
providerDisplayName: 'MSSQL',
|
||||
connectionProvider: connectionProvider,
|
||||
adminServicesProvider: undefined,
|
||||
features: undefined
|
||||
};
|
||||
capabilitiesFromConfig.push(msSQLCapabilities2);
|
||||
let connectionUsingOldMetadata = connections.user.map(c => {
|
||||
c.options[oldOptionName] = 'oldOptionValue';
|
||||
return c;
|
||||
});
|
||||
let configValue = Object.assign({}, connections, { user: connectionUsingOldMetadata });
|
||||
let capabilitiesService2: TypeMoq.Mock<CapabilitiesService> = TypeMoq.Mock.ofType(CapabilitiesService);
|
||||
capabilitiesService2.setup(x => x.getCapabilities()).returns(() => []);
|
||||
capabilitiesService2.setup(x => x.onProviderRegisteredEvent).returns(() => onProviderRegistered.event);
|
||||
workspaceConfigurationServiceMock.setup(x => x.lookup<IConnectionProfileStore[] | IConnectionProfileGroup[] | data.DataProtocolServerCapabilities[]>(
|
||||
Constants.connectionsArrayName))
|
||||
.returns(() => configValue);
|
||||
|
||||
let config = new ConnectionConfig(configEditingServiceMock.object, workspaceConfigurationServiceMock.object, capabilitiesService2.object, capabilitiesFromConfig);
|
||||
let allConnections = config.getConnections(false);
|
||||
allConnections.forEach(element => {
|
||||
assert.notEqual(element.serverName, undefined);
|
||||
assert.notEqual(element.getOptionsKey().indexOf('oldOptionValue|'), -1);
|
||||
});
|
||||
|
||||
onProviderRegistered.fire(msSQLCapabilities);
|
||||
allConnections.forEach(element => {
|
||||
assert.notEqual(element.serverName, undefined);
|
||||
assert.equal(element.getOptionsKey().indexOf('oldOptionValue|'), -1);
|
||||
});
|
||||
});
|
||||
|
||||
test('saveGroup should save the new groups to tree and return the id of the last group name', () => {
|
||||
let config = new ConnectionConfig(undefined, undefined, undefined, undefined);
|
||||
let groups: IConnectionProfileGroup[] = configValueToConcat.user;
|
||||
let expectedLength = configValueToConcat.user.length + 2;
|
||||
let newGroups: string = 'ROOT/g1/g1-1';
|
||||
let color: string = 'red';
|
||||
|
||||
let result: ISaveGroupResult = config.saveGroup(groups, newGroups, color, newGroups);
|
||||
assert.notEqual(result, undefined);
|
||||
assert.equal(result.groups.length, expectedLength, 'The result groups length is invalid');
|
||||
let newGroup = result.groups.find(g => g.name === 'g1-1');
|
||||
assert.equal(result.newGroupId, newGroup.id, 'The groups id is invalid');
|
||||
});
|
||||
|
||||
test('saveGroup should only add the groups that are not in the tree', () => {
|
||||
let config = new ConnectionConfig(undefined, undefined, undefined, undefined);
|
||||
let groups: IConnectionProfileGroup[] = configValueToConcat.user;
|
||||
let expectedLength = configValueToConcat.user.length + 1;
|
||||
let newGroups: string = 'ROOT/g2/g2-5';
|
||||
let color: string = 'red';
|
||||
|
||||
let result: ISaveGroupResult = config.saveGroup(groups, newGroups, color, newGroups);
|
||||
assert.notEqual(result, undefined);
|
||||
assert.equal(result.groups.length, expectedLength, 'The result groups length is invalid');
|
||||
let newGroup = result.groups.find(g => g.name === 'g2-5');
|
||||
assert.equal(result.newGroupId, newGroup.id, 'The groups id is invalid');
|
||||
});
|
||||
|
||||
test('saveGroup should not add any new group if tree already has all the groups in the full path', () => {
|
||||
let config = new ConnectionConfig(undefined, undefined, undefined, undefined);
|
||||
let groups: IConnectionProfileGroup[] = configValueToConcat.user;
|
||||
let expectedLength = configValueToConcat.user.length;
|
||||
let newGroups: string = 'ROOT/g2/g2-1';
|
||||
let color: string = 'red';
|
||||
|
||||
let result: ISaveGroupResult = config.saveGroup(groups, newGroups, color, newGroups);
|
||||
assert.notEqual(result, undefined);
|
||||
assert.equal(result.groups.length, expectedLength, 'The result groups length is invalid');
|
||||
let newGroup = result.groups.find(g => g.name === 'g2-1');
|
||||
assert.equal(result.newGroupId, newGroup.id, 'The groups id is invalid');
|
||||
});
|
||||
|
||||
test('deleteConnection should remove the connection from config', done => {
|
||||
let newProfile: IConnectionProfile = {
|
||||
serverName: 'server3',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'g3',
|
||||
getOptionsKey: undefined,
|
||||
matches: undefined,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: undefined
|
||||
};
|
||||
|
||||
let expectedNumberOfConnections = connections.user.length - 1;
|
||||
workspaceConfigurationServiceMock.setup(x => x.lookup<IConnectionProfileStore[] | IConnectionProfileGroup[] | data.DataProtocolServerCapabilities[]>(
|
||||
Constants.connectionsArrayName))
|
||||
.returns(() => connections);
|
||||
|
||||
let connectionProfile = new ConnectionProfile(msSQLCapabilities, newProfile);
|
||||
connectionProfile.options['databaseDisplayName'] = 'database';
|
||||
|
||||
let config = new ConnectionConfig(configEditingServiceMock.object, workspaceConfigurationServiceMock.object, capabilitiesService.object);
|
||||
config.deleteConnection(connectionProfile).then(() => {
|
||||
configEditingServiceMock.verify(y => y.writeConfiguration(ConfigurationTarget.USER,
|
||||
TypeMoq.It.is<IConfigurationValue>(c => (c.value as IConnectionProfileStore[]).length === expectedNumberOfConnections)), TypeMoq.Times.once());
|
||||
done();
|
||||
}).catch(error => {
|
||||
assert.fail();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('deleteConnectionGroup should remove the children connections and subgroups from config', done => {
|
||||
let newProfile: IConnectionProfile = {
|
||||
serverName: 'server3',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'g3',
|
||||
getOptionsKey: undefined,
|
||||
matches: undefined,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: undefined
|
||||
};
|
||||
let connectionProfile = new ConnectionProfile(msSQLCapabilities, newProfile);
|
||||
connectionProfile.options['databaseDisplayName'] = 'database';
|
||||
|
||||
let connectionProfileGroup = new ConnectionProfileGroup('g3', undefined, 'g3', undefined, undefined);
|
||||
let childGroup = new ConnectionProfileGroup('g3-1', connectionProfileGroup, 'g3-1', undefined, undefined);
|
||||
connectionProfileGroup.addGroups([childGroup]);
|
||||
connectionProfileGroup.addConnections([connectionProfile]);
|
||||
|
||||
let expectedNumberOfConnections = connections.user.length - 1;
|
||||
let expectedNumberOfGroups = configValueToConcat.user.length - 2;
|
||||
workspaceConfigurationServiceMock.setup(x => x.lookup<IConnectionProfileStore[] | IConnectionProfileGroup[] | data.DataProtocolServerCapabilities[]>(
|
||||
Constants.connectionsArrayName))
|
||||
.returns(() => connections);
|
||||
|
||||
workspaceConfigurationServiceMock.setup(x => x.lookup<IConnectionProfileStore[] | IConnectionProfileGroup[] | data.DataProtocolServerCapabilities[]>(
|
||||
Constants.connectionGroupsArrayName))
|
||||
.returns(() => configValueToConcat);
|
||||
|
||||
|
||||
let config = new ConnectionConfig(configEditingServiceMock.object, workspaceConfigurationServiceMock.object, capabilitiesService.object);
|
||||
config.deleteGroup(connectionProfileGroup).then(() => {
|
||||
configEditingServiceMock.verify(y => y.writeConfiguration(ConfigurationTarget.USER,
|
||||
TypeMoq.It.is<IConfigurationValue>(c => (c.value as IConnectionProfileStore[]).length === expectedNumberOfConnections)), TypeMoq.Times.once());
|
||||
configEditingServiceMock.verify(y => y.writeConfiguration(ConfigurationTarget.USER,
|
||||
TypeMoq.It.is<IConfigurationValue>(c => (c.value as IConnectionProfileGroup[]).length === expectedNumberOfGroups)), TypeMoq.Times.once());
|
||||
done();
|
||||
}).catch(error => {
|
||||
assert.fail();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('deleteConnection should not throw error for connection not in config', done => {
|
||||
let newProfile: IConnectionProfile = {
|
||||
serverName: 'server3',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'newid',
|
||||
getOptionsKey: undefined,
|
||||
matches: undefined,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: undefined
|
||||
};
|
||||
|
||||
let expectedNumberOfConnections = connections.user.length;
|
||||
workspaceConfigurationServiceMock.setup(x => x.lookup<IConnectionProfileStore[] | IConnectionProfileGroup[] | data.DataProtocolServerCapabilities[]>(
|
||||
Constants.connectionsArrayName))
|
||||
.returns(() => connections);
|
||||
|
||||
let connectionProfile = new ConnectionProfile(msSQLCapabilities, newProfile);
|
||||
let config = new ConnectionConfig(configEditingServiceMock.object, workspaceConfigurationServiceMock.object, capabilitiesService.object);
|
||||
config.deleteConnection(connectionProfile).then(() => {
|
||||
configEditingServiceMock.verify(y => y.writeConfiguration(ConfigurationTarget.USER,
|
||||
TypeMoq.It.is<IConfigurationValue>(c => (c.value as IConnectionProfileStore[]).length === expectedNumberOfConnections)), TypeMoq.Times.once());
|
||||
done();
|
||||
}).catch(error => {
|
||||
assert.fail();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('renameGroup should change group name', done => {
|
||||
|
||||
let expectedNumberOfConnections = configValueToConcat.user.length;
|
||||
let calledValue: any;
|
||||
let called: boolean = false;
|
||||
let nothing: void;
|
||||
let configEditingServiceMock: TypeMoq.Mock<ConfigurationEditingService> = TypeMoq.Mock.ofType(ConfigurationEditingService);
|
||||
configEditingServiceMock.setup(x => x.writeConfiguration(ConfigurationTarget.USER, TypeMoq.It.isAny())).callback((x: any, val: any) => {
|
||||
calledValue = val.value as IConnectionProfileStore[];
|
||||
}).returns(() => TPromise.as<void>(nothing));
|
||||
workspaceConfigurationServiceMock.setup(x => x.lookup<IConnectionProfileStore[] | IConnectionProfileGroup[] | data.DataProtocolServerCapabilities[]>(
|
||||
Constants.connectionGroupsArrayName))
|
||||
.returns(() => configValueToConcat);
|
||||
|
||||
let connectionProfileGroup = new ConnectionProfileGroup('g-renamed', undefined, 'g2', undefined, undefined);
|
||||
let config = new ConnectionConfig(configEditingServiceMock.object, workspaceConfigurationServiceMock.object, capabilitiesService.object);
|
||||
config.editGroup(connectionProfileGroup).then(() => {
|
||||
configEditingServiceMock.verify(y => y.writeConfiguration(ConfigurationTarget.USER,
|
||||
TypeMoq.It.is<IConfigurationValue>(c => (c.value as IConnectionProfileStore[]).length === expectedNumberOfConnections)), TypeMoq.Times.once());
|
||||
calledValue.forEach(con => {
|
||||
if (con.id === 'g2') {
|
||||
assert.equal(con.name, 'g-renamed', 'Group was not renamed');
|
||||
called = true;
|
||||
}
|
||||
});
|
||||
assert.equal(called, true, 'group was not renamed');
|
||||
}).then(() => done(), (err) => done(err));
|
||||
});
|
||||
|
||||
|
||||
test('change group(parent) for connection group', done => {
|
||||
let expectedNumberOfConnections = configValueToConcat.user.length;
|
||||
let calledValue: any;
|
||||
let nothing: void;
|
||||
let configEditingServiceMock: TypeMoq.Mock<ConfigurationEditingService> = TypeMoq.Mock.ofType(ConfigurationEditingService);
|
||||
configEditingServiceMock.setup(x => x.writeConfiguration(ConfigurationTarget.USER, TypeMoq.It.isAny())).callback((x: any, val: any) => {
|
||||
calledValue = val.value as IConnectionProfileStore[];
|
||||
}).returns(() => TPromise.as<void>(nothing));
|
||||
workspaceConfigurationServiceMock.setup(x => x.lookup<IConnectionProfileStore[] | IConnectionProfileGroup[] | data.DataProtocolServerCapabilities[]>(
|
||||
Constants.connectionGroupsArrayName))
|
||||
.returns(() => configValueToConcat);
|
||||
|
||||
let sourceProfileGroup = new ConnectionProfileGroup('g2', undefined, 'g2', undefined, undefined);
|
||||
let targetProfileGroup = new ConnectionProfileGroup('g3', undefined, 'g3', undefined, undefined);
|
||||
let config = new ConnectionConfig(configEditingServiceMock.object, workspaceConfigurationServiceMock.object, capabilitiesService.object);
|
||||
config.changeGroupIdForConnectionGroup(sourceProfileGroup, targetProfileGroup).then(() => {
|
||||
configEditingServiceMock.verify(y => y.writeConfiguration(ConfigurationTarget.USER,
|
||||
TypeMoq.It.is<IConfigurationValue>(c => (c.value as IConnectionProfileStore[]).length === expectedNumberOfConnections)), TypeMoq.Times.once());
|
||||
calledValue.forEach(con => {
|
||||
if (con.id === 'g2') {
|
||||
assert.equal(con.parentId, 'g3', 'Group parent was not changed');
|
||||
}
|
||||
});
|
||||
}).then(() => done(), (err) => done(err));
|
||||
});
|
||||
|
||||
|
||||
test('change group(parent) for connection', done => {
|
||||
let newProfile: IConnectionProfile = {
|
||||
serverName: 'server3',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'g3',
|
||||
getOptionsKey: () => { return 'connectionId'; },
|
||||
matches: undefined,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: 'test'
|
||||
};
|
||||
|
||||
let expectedNumberOfConnections = connections.user.length;
|
||||
workspaceConfigurationServiceMock.setup(x => x.lookup<IConnectionProfileStore[] | IConnectionProfileGroup[] | data.DataProtocolServerCapabilities[]>(
|
||||
Constants.connectionsArrayName))
|
||||
.returns(() => connections);
|
||||
|
||||
let connectionProfile = new ConnectionProfile(msSQLCapabilities, newProfile);
|
||||
let newId = 'newid';
|
||||
let calledValue: any;
|
||||
let nothing: void;
|
||||
let configEditingServiceMock: TypeMoq.Mock<ConfigurationEditingService> = TypeMoq.Mock.ofType(ConfigurationEditingService);
|
||||
configEditingServiceMock.setup(x => x.writeConfiguration(ConfigurationTarget.USER, TypeMoq.It.isAny())).callback((x: any, val: any) => {
|
||||
calledValue = val.value as IConnectionProfileStore[];
|
||||
}).returns(() => TPromise.as<void>(nothing));
|
||||
configEditingServiceMock.setup(x => x.writeConfiguration(ConfigurationTarget.WORKSPACE, TypeMoq.It.isAny())).callback((x: any, val: any) => {
|
||||
|
||||
}).returns(() => TPromise.as<void>(nothing));
|
||||
|
||||
let config = new ConnectionConfig(configEditingServiceMock.object, workspaceConfigurationServiceMock.object, capabilitiesService.object);
|
||||
config.changeGroupIdForConnection(connectionProfile, newId).then(() => {
|
||||
configEditingServiceMock.verify(y => y.writeConfiguration(ConfigurationTarget.USER,
|
||||
TypeMoq.It.is<IConfigurationValue>(c => (c.value as IConnectionProfileStore[]).length === expectedNumberOfConnections)), TypeMoq.Times.atLeastOnce());
|
||||
calledValue.forEach(con => {
|
||||
});
|
||||
}).then(() => done(), (err) => done(err));
|
||||
});
|
||||
|
||||
test('fixConnectionIds should replace duplicate ids with new ones', (done) => {
|
||||
let profiles: IConnectionProfileStore[] = [
|
||||
{
|
||||
options: {},
|
||||
groupId: '1',
|
||||
id: '1',
|
||||
providerName: undefined,
|
||||
savePassword: true,
|
||||
}, {
|
||||
options: {},
|
||||
groupId: '1',
|
||||
id: '2',
|
||||
providerName: undefined,
|
||||
savePassword: true,
|
||||
}, {
|
||||
options: {},
|
||||
groupId: '1',
|
||||
id: '3',
|
||||
providerName: undefined,
|
||||
savePassword: true,
|
||||
}, {
|
||||
options: {},
|
||||
groupId: '1',
|
||||
id: '2',
|
||||
providerName: undefined,
|
||||
savePassword: true,
|
||||
}, {
|
||||
options: {},
|
||||
groupId: '1',
|
||||
id: '4',
|
||||
providerName: undefined,
|
||||
savePassword: true,
|
||||
}, {
|
||||
options: {},
|
||||
groupId: '1',
|
||||
id: '3',
|
||||
providerName: undefined,
|
||||
savePassword: true,
|
||||
}, {
|
||||
options: {},
|
||||
groupId: '1',
|
||||
id: '2',
|
||||
providerName: undefined,
|
||||
savePassword: true,
|
||||
}
|
||||
];
|
||||
|
||||
let config = new ConnectionConfig(configEditingServiceMock.object, workspaceConfigurationServiceMock.object, capabilitiesService.object);
|
||||
config.fixConnectionIds(profiles);
|
||||
let ids = profiles.map(x => x.id);
|
||||
for (var index = 0; index < ids.length; index++) {
|
||||
var id = ids[index];
|
||||
assert.equal(ids.lastIndexOf(id), index);
|
||||
}
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
87
src/sqltest/parts/connection/connectionDialogService.test.ts
Normal file
87
src/sqltest/parts/connection/connectionDialogService.test.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import { ConnectionDialogService } from 'sql/parts/connection/connectionDialog/connectionDialogService';
|
||||
import { ConnectionDialogWidget } from 'sql/parts/connection/connectionDialog/connectionDialogWidget';
|
||||
import { ConnectionManagementService } from 'sql/parts/connection/common/connectionManagementService';
|
||||
import { ConnectionType, IConnectableInput, IConnectionResult, INewConnectionParams } from 'sql/parts/connection/common/connectionManagement';
|
||||
import { ContextKeyServiceStub } from 'sqltest/stubs/contextKeyServiceStub';
|
||||
import { ErrorMessageServiceStub } from 'sqltest/stubs/errorMessageServiceStub';
|
||||
|
||||
import * as TypeMoq from 'typemoq';
|
||||
|
||||
suite('ConnectionDialogService tests', () => {
|
||||
|
||||
let connectionDialogService: ConnectionDialogService;
|
||||
let mockConnectionManagementService: TypeMoq.Mock<ConnectionManagementService>;
|
||||
let mockConnectionDialog: TypeMoq.Mock<ConnectionDialogWidget>;
|
||||
|
||||
setup(() => {
|
||||
let errorMessageService = getMockErrorMessageService();
|
||||
connectionDialogService = new ConnectionDialogService(undefined, undefined, undefined, errorMessageService.object, undefined);
|
||||
mockConnectionManagementService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Strict, {}, {});
|
||||
(connectionDialogService as any)._connectionManagementService = mockConnectionManagementService.object;
|
||||
mockConnectionDialog = TypeMoq.Mock.ofType(ConnectionDialogWidget, TypeMoq.MockBehavior.Strict,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
new ContextKeyServiceStub()
|
||||
);
|
||||
mockConnectionDialog.setup(c => c.resetConnection());
|
||||
(connectionDialogService as any)._connectionDialog = mockConnectionDialog.object;
|
||||
});
|
||||
|
||||
function getMockErrorMessageService(): TypeMoq.Mock<ErrorMessageServiceStub> {
|
||||
let mockMessageService = TypeMoq.Mock.ofType(ErrorMessageServiceStub);
|
||||
mockMessageService.setup(x => x.showDialog(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()));
|
||||
return mockMessageService;
|
||||
}
|
||||
|
||||
function testHandleDefaultOnConnectUri(isEditor: boolean): Thenable<void> {
|
||||
let testUri = 'test_uri';
|
||||
let connectionParams = <INewConnectionParams>{
|
||||
connectionType: isEditor ? ConnectionType.editor : ConnectionType.default,
|
||||
input: <IConnectableInput>{
|
||||
uri: testUri,
|
||||
onConnectStart: undefined,
|
||||
onConnectSuccess: undefined,
|
||||
onConnectReject: undefined,
|
||||
onDisconnect: undefined
|
||||
},
|
||||
runQueryOnCompletion: undefined,
|
||||
querySelection: undefined
|
||||
};
|
||||
mockConnectionManagementService.setup(x => x.connectAndSaveProfile(undefined, TypeMoq.It.is(_ => true), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(
|
||||
() => Promise.resolve(<IConnectionResult>{ connected: true, errorMessage: undefined, errorCode: undefined }));
|
||||
|
||||
// If I call handleDefaultOnConnect with the given parameters
|
||||
let thenable: Thenable<void> = (connectionDialogService as any).handleDefaultOnConnect(connectionParams, undefined);
|
||||
return thenable.then(() => {
|
||||
// Then the Connection Management Service's connect method was called with the expected URI
|
||||
let expectedUri = isEditor ? testUri : undefined;
|
||||
mockConnectionManagementService.verify(
|
||||
x => x.connectAndSaveProfile(undefined, TypeMoq.It.is(uri => uri === expectedUri), TypeMoq.It.isAny(), TypeMoq.It.isAny()),
|
||||
TypeMoq.Times.once());
|
||||
});
|
||||
}
|
||||
|
||||
test('handleDefaultOnConnect uses params URI for editor connections', done => {
|
||||
testHandleDefaultOnConnectUri(true).then(() => done(), err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
test('handleDefaultOnConnect uses undefined URI for non-editor connections', done => {
|
||||
testHandleDefaultOnConnectUri(false).then(() => done(), err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
563
src/sqltest/parts/connection/connectionManagementService.test.ts
Normal file
563
src/sqltest/parts/connection/connectionManagementService.test.ts
Normal file
@@ -0,0 +1,563 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import { ConnectionDialogTestService } from 'sqltest/stubs/connectionDialogTestService';
|
||||
import { ConnectionManagementService } from 'sql/parts/connection/common/connectionManagementService';
|
||||
import { ConnectionStatusManager } from 'sql/parts/connection/common/connectionStatusManager';
|
||||
import { ConnectionStore } from 'sql/parts/connection/common/connectionStore';
|
||||
import {
|
||||
INewConnectionParams, ConnectionType,
|
||||
IConnectionCompletionOptions, IConnectionResult,
|
||||
RunQueryOnConnectionMode
|
||||
} from 'sql/parts/connection/common/connectionManagement';
|
||||
import * as Constants from 'sql/parts/connection/common/constants';
|
||||
import * as Utils from 'sql/parts/connection/common/utils';
|
||||
|
||||
import { WorkbenchEditorTestService } from 'sqltest/stubs/workbenchEditorTestService';
|
||||
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
||||
import { EditorGroupTestService } from 'sqltest/stubs/editorGroupService';
|
||||
import { CapabilitiesTestService } from 'sqltest/stubs/capabilitiesTestService';
|
||||
import { ConnectionProviderStub } from 'sqltest/stubs/connectionProviderStub';
|
||||
|
||||
import * as data from 'data';
|
||||
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { WorkspaceConfigurationTestService } from 'sqltest/stubs/workspaceConfigurationTestService';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as TypeMoq from 'typemoq';
|
||||
|
||||
suite('SQL ConnectionManagementService tests', () => {
|
||||
|
||||
let capabilitiesService: CapabilitiesTestService;
|
||||
let connectionDialogService: TypeMoq.Mock<ConnectionDialogTestService>;
|
||||
let connectionStore: TypeMoq.Mock<ConnectionStore>;
|
||||
let workbenchEditorService: TypeMoq.Mock<WorkbenchEditorTestService>;
|
||||
let editorGroupService: TypeMoq.Mock<EditorGroupTestService>;
|
||||
let connectionStatusManager: ConnectionStatusManager;
|
||||
let mssqlConnectionProvider: TypeMoq.Mock<ConnectionProviderStub>;
|
||||
let otherConnectionProvider: TypeMoq.Mock<ConnectionProviderStub>;
|
||||
let workspaceConfigurationServiceMock: TypeMoq.Mock<WorkspaceConfigurationTestService>;
|
||||
|
||||
let none: void;
|
||||
|
||||
let connectionProfile: IConnectionProfile = {
|
||||
serverName: 'new server',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: 'integrated',
|
||||
savePassword: true,
|
||||
groupFullName: 'g2/g2-2',
|
||||
groupId: 'group id',
|
||||
getOptionsKey: () => { return 'connectionId'; },
|
||||
matches: undefined,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: undefined
|
||||
};
|
||||
let connectionProfileWithEmptySavedPassword: IConnectionProfile =
|
||||
Object.assign({}, connectionProfile, { password: '', serverName: connectionProfile.serverName + 1 });
|
||||
let connectionProfileWithEmptyUnsavedPassword: IConnectionProfile =
|
||||
Object.assign({}, connectionProfile, { password: '', serverName: connectionProfile.serverName + 2, savePassword: false });
|
||||
|
||||
let connectionManagementService: ConnectionManagementService;
|
||||
let configResult: { [key: string]: any } = {};
|
||||
|
||||
setup(() => {
|
||||
|
||||
capabilitiesService = new CapabilitiesTestService();
|
||||
connectionDialogService = TypeMoq.Mock.ofType(ConnectionDialogTestService);
|
||||
connectionStore = TypeMoq.Mock.ofType(ConnectionStore);
|
||||
workbenchEditorService = TypeMoq.Mock.ofType(WorkbenchEditorTestService);
|
||||
editorGroupService = TypeMoq.Mock.ofType(EditorGroupTestService);
|
||||
connectionStatusManager = new ConnectionStatusManager(capabilitiesService);
|
||||
mssqlConnectionProvider = TypeMoq.Mock.ofType(ConnectionProviderStub);
|
||||
otherConnectionProvider = TypeMoq.Mock.ofType(ConnectionProviderStub);
|
||||
|
||||
connectionDialogService.setup(x => x.showDialog(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny(), undefined)).returns(() => TPromise.as(none));
|
||||
connectionDialogService.setup(x => x.showDialog(TypeMoq.It.isAny(), TypeMoq.It.isAny(), undefined, undefined)).returns(() => TPromise.as(none));
|
||||
connectionDialogService.setup(x => x.showDialog(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => TPromise.as(none));
|
||||
connectionDialogService.setup(x => x.showDialog(TypeMoq.It.isAny(), TypeMoq.It.isAny(), undefined, TypeMoq.It.isAny())).returns(() => TPromise.as(none));
|
||||
|
||||
connectionStore.setup(x => x.addActiveConnection(TypeMoq.It.isAny())).returns(() => Promise.resolve());
|
||||
connectionStore.setup(x => x.saveProfile(TypeMoq.It.isAny())).returns(() => Promise.resolve(connectionProfile));
|
||||
workbenchEditorService.setup(x => x.openEditor(undefined, TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => TPromise.as(undefined));
|
||||
editorGroupService.setup(x => x.getStacksModel()).returns(() => undefined);
|
||||
connectionStore.setup(x => x.addSavedPassword(TypeMoq.It.is<IConnectionProfile>(
|
||||
c => c.serverName === connectionProfile.serverName))).returns(() => Promise.resolve({ profile: connectionProfile, savedCred: true }));
|
||||
connectionStore.setup(x => x.addSavedPassword(TypeMoq.It.is<IConnectionProfile>(
|
||||
c => c.serverName === connectionProfileWithEmptySavedPassword.serverName))).returns(
|
||||
() => Promise.resolve({ profile: connectionProfileWithEmptySavedPassword, savedCred: true }));
|
||||
connectionStore.setup(x => x.addSavedPassword(TypeMoq.It.is<IConnectionProfile>(
|
||||
c => c.serverName === connectionProfileWithEmptyUnsavedPassword.serverName))).returns(
|
||||
() => Promise.resolve({ profile: connectionProfileWithEmptyUnsavedPassword, savedCred: false }));
|
||||
connectionStore.setup(x => x.isPasswordRequired(TypeMoq.It.isAny())).returns(() => true);
|
||||
|
||||
mssqlConnectionProvider.setup(x => x.connect(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => undefined);
|
||||
otherConnectionProvider.setup(x => x.connect(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => undefined);
|
||||
|
||||
// setup configuration to return a config that can be modified later.
|
||||
|
||||
workspaceConfigurationServiceMock = TypeMoq.Mock.ofType(WorkspaceConfigurationTestService);
|
||||
workspaceConfigurationServiceMock.setup(x => x.getConfiguration(Constants.sqlConfigSectionName))
|
||||
.returns(() => configResult);
|
||||
|
||||
connectionManagementService = createConnectionManagementService();
|
||||
|
||||
connectionManagementService.registerProvider('MSSQL', mssqlConnectionProvider.object);
|
||||
});
|
||||
|
||||
function createConnectionManagementService(): ConnectionManagementService {
|
||||
let connectionManagementService = new ConnectionManagementService(
|
||||
undefined,
|
||||
connectionStore.object,
|
||||
connectionDialogService.object,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
workbenchEditorService.object,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
workspaceConfigurationServiceMock.object,
|
||||
undefined,
|
||||
capabilitiesService,
|
||||
undefined,
|
||||
editorGroupService.object,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined
|
||||
);
|
||||
return connectionManagementService;
|
||||
}
|
||||
|
||||
function verifyShowDialog(connectionProfile: IConnectionProfile, connectionType: ConnectionType, uri: string, error?: string, didShow: boolean = true): void {
|
||||
|
||||
if (connectionProfile) {
|
||||
connectionDialogService.verify(x => x.showDialog(
|
||||
TypeMoq.It.isAny(),
|
||||
TypeMoq.It.is<INewConnectionParams>(p => p.connectionType === connectionType && (uri === undefined || p.input.uri === uri)),
|
||||
TypeMoq.It.is<IConnectionProfile>(c => c.serverName === connectionProfile.serverName), error),
|
||||
didShow ? TypeMoq.Times.once() : TypeMoq.Times.never());
|
||||
|
||||
} else {
|
||||
connectionDialogService.verify(x => x.showDialog(
|
||||
TypeMoq.It.isAny(),
|
||||
TypeMoq.It.is<INewConnectionParams>(p => p.connectionType === connectionType && ((uri === undefined && p.input === undefined) || p.input.uri === uri)),
|
||||
undefined, error), didShow ? TypeMoq.Times.once() : TypeMoq.Times.never());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function verifyOptions(options?: IConnectionCompletionOptions, fromDialog?: boolean): void {
|
||||
|
||||
if (options) {
|
||||
if (options.saveTheConnection) {
|
||||
connectionStore.verify(x => x.saveProfile(TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||
}
|
||||
if (options.showDashboard) {
|
||||
workbenchEditorService.verify(x => x.openEditor(undefined, TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||
}
|
||||
}
|
||||
|
||||
if (fromDialog !== undefined && !fromDialog) {
|
||||
connectionStore.verify(x => x.addSavedPassword(TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function connect(uri: string, options?: IConnectionCompletionOptions, fromDialog?: boolean, connection?: IConnectionProfile, error?: string): Promise<IConnectionResult> {
|
||||
let connectionToUse = connection ? connection : connectionProfile;
|
||||
return new Promise<IConnectionResult>((resolve, reject) => {
|
||||
let id = connectionToUse.getOptionsKey();
|
||||
let defaultUri = 'connection://' + (id ? id : connection.serverName + ':' + connection.databaseName);
|
||||
connectionManagementService.onConnectionRequestSent(() => {
|
||||
let info: data.ConnectionInfoSummary = {
|
||||
connectionId: error ? undefined : 'id',
|
||||
connectionSummary: {
|
||||
databaseName: connectionToUse.databaseName,
|
||||
serverName: connectionToUse.serverName,
|
||||
userName: connectionToUse.userName
|
||||
},
|
||||
errorMessage: error,
|
||||
errorNumber: undefined,
|
||||
messages: error,
|
||||
ownerUri: uri ? uri : defaultUri,
|
||||
serverInfo: undefined
|
||||
};
|
||||
connectionManagementService.onConnectionComplete(0, info);
|
||||
});
|
||||
connectionManagementService.cancelConnectionForUri(uri).then(() => {
|
||||
if (fromDialog) {
|
||||
resolve(connectionManagementService.connectAndSaveProfile(connectionToUse, uri, options));
|
||||
} else {
|
||||
resolve(connectionManagementService.connect(connectionToUse, uri, options));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
test('showConnectionDialog should open the dialog with default type given no parameters', done => {
|
||||
connectionManagementService.showConnectionDialog().then(() => {
|
||||
verifyShowDialog(undefined, ConnectionType.default, undefined);
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
test('showConnectionDialog should open the dialog with given type given valid input', done => {
|
||||
let params: INewConnectionParams = {
|
||||
connectionType: ConnectionType.editor,
|
||||
input: {
|
||||
onConnectReject: undefined,
|
||||
onConnectStart: undefined,
|
||||
onDisconnect: undefined,
|
||||
onConnectSuccess: undefined,
|
||||
uri: 'Editor Uri'
|
||||
},
|
||||
runQueryOnCompletion: RunQueryOnConnectionMode.executeQuery
|
||||
};
|
||||
connectionManagementService.showConnectionDialog(params).then(() => {
|
||||
verifyShowDialog(undefined, params.connectionType, params.input.uri);
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
test('showConnectionDialog should pass the model to the dialog if there is a model assigned to the uri', done => {
|
||||
let params: INewConnectionParams = {
|
||||
connectionType: ConnectionType.editor,
|
||||
input: {
|
||||
onConnectReject: undefined,
|
||||
onConnectStart: undefined,
|
||||
onDisconnect: undefined,
|
||||
onConnectSuccess: undefined,
|
||||
uri: 'Editor Uri'
|
||||
},
|
||||
runQueryOnCompletion: RunQueryOnConnectionMode.executeQuery
|
||||
};
|
||||
|
||||
connect(params.input.uri).then(() => {
|
||||
let saveConnection = connectionManagementService.getConnectionProfile(params.input.uri);
|
||||
|
||||
assert.notEqual(saveConnection, undefined, `profile was not added to the connections`);
|
||||
assert.equal(saveConnection.serverName, connectionProfile.serverName, `Server names are different`);
|
||||
connectionManagementService.showConnectionDialog(params).then(() => {
|
||||
verifyShowDialog(connectionProfile, params.connectionType, params.input.uri);
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('connect should save profile given options with saveProfile set to true', done => {
|
||||
let uri: string = 'Editor Uri';
|
||||
let options: IConnectionCompletionOptions = {
|
||||
params: undefined,
|
||||
saveTheConnection: true,
|
||||
showDashboard: false,
|
||||
showConnectionDialogOnError: false,
|
||||
showFirewallRuleOnError: false
|
||||
};
|
||||
|
||||
connect(uri, options).then(() => {
|
||||
verifyOptions(options);
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
/* Andresse 10/5/17 commented this test out since it was only working before my changes by the chance of how Promises work
|
||||
If we want to continue to test this, the connection logic needs to be rewritten to actually wait for everything to be done before it resolves */
|
||||
// test('connect should show dashboard given options with showDashboard set to true', done => {
|
||||
// let uri: string = 'Editor Uri';
|
||||
// let options: IConnectionCompletionOptions = {
|
||||
// params: undefined,
|
||||
// saveTheConnection: false,
|
||||
// showDashboard: true,
|
||||
// showConnectionDialogOnError: false
|
||||
// };
|
||||
|
||||
// connect(uri, options).then(() => {
|
||||
// verifyOptions(options);
|
||||
// done();
|
||||
// }).catch(err => {
|
||||
// done(err);
|
||||
// });
|
||||
// });
|
||||
|
||||
test('connect should pass the params in options to onConnectSuccess callback', done => {
|
||||
let uri: string = 'Editor Uri';
|
||||
let paramsInOnConnectSuccess: INewConnectionParams;
|
||||
let options: IConnectionCompletionOptions = {
|
||||
params: {
|
||||
connectionType: ConnectionType.editor,
|
||||
input: {
|
||||
onConnectSuccess: (params?: INewConnectionParams) => {
|
||||
paramsInOnConnectSuccess = params;
|
||||
},
|
||||
onConnectReject: undefined,
|
||||
onConnectStart: undefined,
|
||||
onDisconnect: undefined,
|
||||
uri: uri
|
||||
},
|
||||
querySelection: undefined,
|
||||
runQueryOnCompletion: RunQueryOnConnectionMode.none
|
||||
},
|
||||
saveTheConnection: true,
|
||||
showDashboard: false,
|
||||
showConnectionDialogOnError: true,
|
||||
showFirewallRuleOnError: false
|
||||
};
|
||||
|
||||
connect(uri, options).then(() => {
|
||||
verifyOptions(options);
|
||||
assert.notEqual(paramsInOnConnectSuccess, undefined);
|
||||
assert.equal(paramsInOnConnectSuccess.connectionType, options.params.connectionType);
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
test('connectAndSaveProfile should show not load the password', done => {
|
||||
let uri: string = 'Editor Uri';
|
||||
let options: IConnectionCompletionOptions = undefined;
|
||||
|
||||
connect(uri, options, true).then(() => {
|
||||
verifyOptions(options, true);
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
test('connect with undefined uri and options should connect using the default uri', done => {
|
||||
let uri = undefined;
|
||||
let options: IConnectionCompletionOptions = undefined;
|
||||
|
||||
connect(uri, options).then(() => {
|
||||
assert.equal(connectionManagementService.isProfileConnected(connectionProfile), true);
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
test('failed connection should open the dialog if connection fails', done => {
|
||||
let uri = undefined;
|
||||
let error: string = 'error';
|
||||
let expectedConnection: boolean = false;
|
||||
let expectedError: string = error;
|
||||
let options: IConnectionCompletionOptions = {
|
||||
params: undefined,
|
||||
saveTheConnection: false,
|
||||
showDashboard: false,
|
||||
showConnectionDialogOnError: true,
|
||||
showFirewallRuleOnError: false
|
||||
};
|
||||
|
||||
connect(uri, options, false, connectionProfile, error).then(result => {
|
||||
assert.equal(result.connected, expectedConnection);
|
||||
assert.equal(result.errorMessage, expectedError);
|
||||
verifyShowDialog(connectionProfile, ConnectionType.default, uri, error);
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
test('failed connection should not open the dialog if the option is set to false even if connection fails', done => {
|
||||
let uri = undefined;
|
||||
let error: string = 'error when options set to false';
|
||||
let expectedConnection: boolean = false;
|
||||
let expectedError: string = error;
|
||||
let options: IConnectionCompletionOptions = {
|
||||
params: undefined,
|
||||
saveTheConnection: false,
|
||||
showDashboard: false,
|
||||
showConnectionDialogOnError: false,
|
||||
showFirewallRuleOnError: false
|
||||
};
|
||||
|
||||
connect(uri, options, false, connectionProfile, error).then(result => {
|
||||
assert.equal(result.connected, expectedConnection);
|
||||
assert.equal(result.errorMessage, expectedError);
|
||||
// TODO: not sure how to verify not called
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
test('connect when password is empty and unsaved should open the dialog', done => {
|
||||
let uri = undefined;
|
||||
let expectedConnection: boolean = false;
|
||||
let expectedError: string = undefined;
|
||||
let options: IConnectionCompletionOptions = {
|
||||
params: undefined,
|
||||
saveTheConnection: false,
|
||||
showDashboard: false,
|
||||
showConnectionDialogOnError: true,
|
||||
showFirewallRuleOnError: false
|
||||
};
|
||||
|
||||
connect(uri, options, false, connectionProfileWithEmptyUnsavedPassword).then(result => {
|
||||
assert.equal(result.connected, expectedConnection);
|
||||
assert.equal(result.errorMessage, expectedError);
|
||||
verifyShowDialog(connectionProfileWithEmptyUnsavedPassword, ConnectionType.default, uri, expectedError);
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
test('connect when password is empty and saved should not open the dialog', done => {
|
||||
let uri = undefined;
|
||||
let expectedConnection: boolean = true;
|
||||
let expectedError: string = undefined;
|
||||
let options: IConnectionCompletionOptions = {
|
||||
params: undefined,
|
||||
saveTheConnection: false,
|
||||
showDashboard: false,
|
||||
showConnectionDialogOnError: true,
|
||||
showFirewallRuleOnError: false
|
||||
};
|
||||
|
||||
connect(uri, options, false, connectionProfileWithEmptySavedPassword).then(result => {
|
||||
assert.equal(result.connected, expectedConnection);
|
||||
assert.equal(result.errorMessage, expectedError);
|
||||
verifyShowDialog(connectionProfileWithEmptySavedPassword, ConnectionType.default, uri, expectedError, false);
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
test('connect from editor when empty password when it is required and saved should not open the dialog', done => {
|
||||
let uri = 'editor 3';
|
||||
let expectedConnection: boolean = true;
|
||||
let expectedError: string = undefined;
|
||||
let options: IConnectionCompletionOptions = {
|
||||
params: {
|
||||
connectionType: ConnectionType.editor,
|
||||
input: {
|
||||
onConnectSuccess: undefined,
|
||||
onConnectReject: undefined,
|
||||
onConnectStart: undefined,
|
||||
onDisconnect: undefined,
|
||||
uri: uri
|
||||
},
|
||||
querySelection: undefined,
|
||||
runQueryOnCompletion: RunQueryOnConnectionMode.none
|
||||
},
|
||||
saveTheConnection: true,
|
||||
showDashboard: false,
|
||||
showConnectionDialogOnError: true,
|
||||
showFirewallRuleOnError: false
|
||||
};
|
||||
|
||||
connect(uri, options, false, connectionProfileWithEmptySavedPassword).then(result => {
|
||||
assert.equal(result.connected, expectedConnection);
|
||||
assert.equal(result.errorMessage, expectedError);
|
||||
verifyShowDialog(connectionProfileWithEmptySavedPassword, ConnectionType.editor, uri, expectedError, false);
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
test('doChangeLanguageFlavor should throw on unknown provider', done => {
|
||||
// given a provider that will never exist
|
||||
let invalidProvider = 'notaprovider';
|
||||
// when I call doChangeLanguageFlavor
|
||||
// Then I expect it to throw
|
||||
assert.throws(() => connectionManagementService.doChangeLanguageFlavor('file://my.sql', 'sql', invalidProvider));
|
||||
done();
|
||||
});
|
||||
|
||||
test('doChangeLanguageFlavor should send event for known provider', done => {
|
||||
// given a provider that is registered
|
||||
let uri = 'file://my.sql';
|
||||
let language = 'sql';
|
||||
let flavor = 'MSSQL';
|
||||
// when I call doChangeLanguageFlavor
|
||||
try {
|
||||
let called = false;
|
||||
connectionManagementService.onLanguageFlavorChanged((changeParams: data.DidChangeLanguageFlavorParams) => {
|
||||
called = true;
|
||||
assert.equal(changeParams.uri, uri);
|
||||
assert.equal(changeParams.language, language);
|
||||
assert.equal(changeParams.flavor, flavor);
|
||||
});
|
||||
connectionManagementService.doChangeLanguageFlavor(uri, language, flavor);
|
||||
assert.ok(called, 'expected onLanguageFlavorChanged event to be sent');
|
||||
done();
|
||||
} catch (error) {
|
||||
done(error);
|
||||
}
|
||||
});
|
||||
|
||||
test('ensureDefaultLanguageFlavor should not send event if uri is connected', done => {
|
||||
let uri: string = 'Editor Uri';
|
||||
let options: IConnectionCompletionOptions = {
|
||||
params: undefined,
|
||||
saveTheConnection: false,
|
||||
showDashboard: false,
|
||||
showConnectionDialogOnError: false,
|
||||
showFirewallRuleOnError: false
|
||||
};
|
||||
let connectionManagementService = createConnectionManagementService();
|
||||
let called = false;
|
||||
connectionManagementService.onLanguageFlavorChanged((changeParams: data.DidChangeLanguageFlavorParams) => {
|
||||
called = true;
|
||||
});
|
||||
connect(uri, options).then(() => {
|
||||
connectionManagementService.ensureDefaultLanguageFlavor(uri);
|
||||
assert.equal(called, false, 'do not expect flavor change to be called');
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
test('getConnectionId returns the URI associated with a connection that has had its database filled in', done => {
|
||||
// Set up the connection management service with a connection corresponding to a default database
|
||||
let dbName = 'master';
|
||||
let serverName = 'test_server';
|
||||
let userName = 'test_user';
|
||||
let connectionProfileWithoutDb: IConnectionProfile = Object.assign(connectionProfile,
|
||||
{ serverName: serverName, databaseName: '', userName: userName, getOptionsKey: () => undefined });
|
||||
let connectionProfileWithDb: IConnectionProfile = Object.assign(connectionProfileWithoutDb, { databaseName: dbName });
|
||||
// Save the database with a URI that has the database name filled in, to mirror Carbon's behavior
|
||||
let ownerUri = Utils.generateUri(connectionProfileWithDb);
|
||||
connect(ownerUri, undefined, false, connectionProfileWithoutDb).then(() => {
|
||||
try {
|
||||
// If I get the URI for the connection with or without a database from the connection management service
|
||||
let actualUriWithDb = connectionManagementService.getConnectionId(connectionProfileWithDb);
|
||||
let actualUriWithoutDb = connectionManagementService.getConnectionId(connectionProfileWithoutDb);
|
||||
|
||||
// Then the retrieved URIs should match the one on the connection
|
||||
let expectedUri = Utils.generateUri(connectionProfileWithoutDb);
|
||||
assert.equal(actualUriWithDb, expectedUri);
|
||||
assert.equal(actualUriWithoutDb, expectedUri);
|
||||
done();
|
||||
} catch (err) {
|
||||
done(err);
|
||||
}
|
||||
}, err => done(err));
|
||||
});
|
||||
});
|
||||
206
src/sqltest/parts/connection/connectionProfile.test.ts
Normal file
206
src/sqltest/parts/connection/connectionProfile.test.ts
Normal file
@@ -0,0 +1,206 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
|
||||
import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
|
||||
import { IConnectionProfile, IConnectionProfileStore } from 'sql/parts/connection/common/interfaces';
|
||||
import data = require('data');
|
||||
import * as assert from 'assert';
|
||||
|
||||
suite('SQL ConnectionProfileInfo tests', () => {
|
||||
let msSQLCapabilities: data.DataProtocolServerCapabilities;
|
||||
|
||||
let connectionProfile: IConnectionProfile = {
|
||||
serverName: 'new server',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g2/g2-2',
|
||||
groupId: 'group id',
|
||||
getOptionsKey: undefined,
|
||||
matches: undefined,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: undefined
|
||||
};
|
||||
|
||||
let storedProfile: IConnectionProfileStore = {
|
||||
groupId: 'groupId',
|
||||
id: 'id',
|
||||
options: {
|
||||
serverName: 'new server',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: ''
|
||||
},
|
||||
providerName: 'MSSQL',
|
||||
savePassword: true
|
||||
};
|
||||
|
||||
setup(() => {
|
||||
let capabilities: data.DataProtocolServerCapabilities[] = [];
|
||||
let connectionProvider: data.ConnectionProviderOptions = {
|
||||
options: [
|
||||
{
|
||||
name: 'serverName',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 0,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'databaseName',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 1,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'userName',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 3,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'authenticationType',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 2,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'password',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 4,
|
||||
valueType: 0
|
||||
}
|
||||
]
|
||||
};
|
||||
msSQLCapabilities = {
|
||||
protocolVersion: '1',
|
||||
providerName: 'MSSQL',
|
||||
providerDisplayName: 'MSSQL',
|
||||
connectionProvider: connectionProvider,
|
||||
adminServicesProvider: undefined,
|
||||
features: undefined
|
||||
};
|
||||
capabilities.push(msSQLCapabilities);
|
||||
});
|
||||
|
||||
test('set properties should set the values correctly', () => {
|
||||
let conn = new ConnectionProfile(msSQLCapabilities, undefined);
|
||||
assert.equal(conn.serverName, undefined);
|
||||
conn.serverName = connectionProfile.serverName;
|
||||
conn.databaseName = connectionProfile.databaseName;
|
||||
conn.authenticationType = connectionProfile.authenticationType;
|
||||
conn.password = connectionProfile.password;
|
||||
conn.userName = connectionProfile.userName;
|
||||
conn.groupId = connectionProfile.groupId;
|
||||
conn.groupFullName = connectionProfile.groupFullName;
|
||||
conn.savePassword = connectionProfile.savePassword;
|
||||
assert.equal(conn.serverName, connectionProfile.serverName);
|
||||
assert.equal(conn.databaseName, connectionProfile.databaseName);
|
||||
assert.equal(conn.authenticationType, connectionProfile.authenticationType);
|
||||
assert.equal(conn.password, connectionProfile.password);
|
||||
assert.equal(conn.userName, connectionProfile.userName);
|
||||
assert.equal(conn.groupId, connectionProfile.groupId);
|
||||
assert.equal(conn.groupFullName, connectionProfile.groupFullName);
|
||||
assert.equal(conn.savePassword, connectionProfile.savePassword);
|
||||
});
|
||||
|
||||
test('constructor should initialize the options given a valid model', () => {
|
||||
let conn = new ConnectionProfile(msSQLCapabilities, connectionProfile);
|
||||
|
||||
assert.equal(conn.serverName, connectionProfile.serverName);
|
||||
assert.equal(conn.databaseName, connectionProfile.databaseName);
|
||||
assert.equal(conn.authenticationType, connectionProfile.authenticationType);
|
||||
assert.equal(conn.password, connectionProfile.password);
|
||||
assert.equal(conn.userName, connectionProfile.userName);
|
||||
assert.equal(conn.groupId, connectionProfile.groupId);
|
||||
assert.equal(conn.groupFullName, connectionProfile.groupFullName);
|
||||
assert.equal(conn.savePassword, connectionProfile.savePassword);
|
||||
});
|
||||
|
||||
test('getOptionsKey should create a valid unique id', () => {
|
||||
let conn = new ConnectionProfile(msSQLCapabilities, connectionProfile);
|
||||
let expectedId = 'providerName:MSSQL|authenticationType:|databaseName:database|serverName:new server|userName:user|databaseDisplayName:database|group:group id';
|
||||
let id = conn.getOptionsKey();
|
||||
assert.equal(id, expectedId);
|
||||
});
|
||||
|
||||
test('createFromStoredProfile should create connection profile from stored profile', () => {
|
||||
let savedProfile = storedProfile;
|
||||
let connectionProfile = ConnectionProfile.createFromStoredProfile(savedProfile, msSQLCapabilities);
|
||||
assert.equal(savedProfile.groupId, connectionProfile.groupId);
|
||||
assert.deepEqual(savedProfile.options, connectionProfile.options);
|
||||
assert.deepEqual(savedProfile.providerName, connectionProfile.providerName);
|
||||
assert.deepEqual(savedProfile.savePassword, connectionProfile.savePassword);
|
||||
assert.deepEqual(savedProfile.id, connectionProfile.id);
|
||||
});
|
||||
|
||||
test('createFromStoredProfile should set the id to new guid if not set in stored profile', () => {
|
||||
let savedProfile = Object.assign({}, storedProfile, { id: undefined });
|
||||
let connectionProfile = ConnectionProfile.createFromStoredProfile(savedProfile, msSQLCapabilities);
|
||||
assert.equal(savedProfile.groupId, connectionProfile.groupId);
|
||||
assert.deepEqual(savedProfile.options, connectionProfile.options);
|
||||
assert.deepEqual(savedProfile.providerName, connectionProfile.providerName);
|
||||
assert.equal(savedProfile.savePassword, connectionProfile.savePassword);
|
||||
assert.notEqual(connectionProfile.id, undefined);
|
||||
assert.equal(savedProfile.id, undefined);
|
||||
});
|
||||
|
||||
test('withoutPassword should create a new instance without password', () => {
|
||||
let conn = new ConnectionProfile(msSQLCapabilities, connectionProfile);
|
||||
assert.notEqual(conn.password, '');
|
||||
let withoutPassword = conn.withoutPassword();
|
||||
assert.equal(withoutPassword.password, '');
|
||||
});
|
||||
|
||||
test('unique id should not include password', () => {
|
||||
let conn = new ConnectionProfile(msSQLCapabilities, connectionProfile);
|
||||
let withoutPassword = conn.withoutPassword();
|
||||
assert.equal(withoutPassword.getOptionsKey(), conn.getOptionsKey());
|
||||
});
|
||||
|
||||
test('cloneWithDatabase should create new profile with new id', () => {
|
||||
let conn = new ConnectionProfile(msSQLCapabilities, connectionProfile);
|
||||
let newProfile = conn.cloneWithDatabase('new db');
|
||||
assert.notEqual(newProfile.id, conn.id);
|
||||
assert.equal(newProfile.databaseName, 'new db');
|
||||
});
|
||||
});
|
||||
148
src/sqltest/parts/connection/connectionProfileGroup.test.ts
Normal file
148
src/sqltest/parts/connection/connectionProfileGroup.test.ts
Normal file
@@ -0,0 +1,148 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
|
||||
import { ConnectionProfileGroup } from 'sql/parts/connection/common/connectionProfileGroup';
|
||||
import * as assert from 'assert';
|
||||
|
||||
suite('SQL ConnectionProfileGroup tests', () => {
|
||||
let root: ConnectionProfileGroup;
|
||||
let Groups1 = 'G1';
|
||||
let Groups11 = 'G11';
|
||||
let Groups2 = 'G2';
|
||||
let group1Node: ConnectionProfileGroup;
|
||||
let group11Node: ConnectionProfileGroup;
|
||||
let group2Node: ConnectionProfileGroup;
|
||||
setup(() => {
|
||||
root = new ConnectionProfileGroup(ConnectionProfileGroup.RootGroupName, undefined, ConnectionProfileGroup.RootGroupName, undefined, undefined);
|
||||
|
||||
group1Node = new ConnectionProfileGroup(Groups1, root, Groups1, undefined, undefined);
|
||||
group2Node = new ConnectionProfileGroup(Groups2, root, Groups2, undefined, undefined);
|
||||
group11Node = new ConnectionProfileGroup(Groups11, root, Groups11, undefined, undefined);
|
||||
root.addGroups([group1Node]);
|
||||
group1Node.addGroups([group11Node]);
|
||||
root.addGroups([group2Node]);
|
||||
});
|
||||
|
||||
test('Root name should be returned as empty string', () => {
|
||||
assert.equal(root.name, '');
|
||||
});
|
||||
|
||||
test('Fullname should return the group full name correctly', () => {
|
||||
assert.equal(group1Node.fullName, 'G1');
|
||||
assert.equal(group2Node.fullName, 'G2');
|
||||
assert.equal(group11Node.fullName, 'G1/G11');
|
||||
});
|
||||
|
||||
test('getGroupFullNameParts should return a list With ROOT in it given an empty string', () => {
|
||||
let groupFullName: string = '';
|
||||
let expected: string[] = [ConnectionProfileGroup.RootGroupName];
|
||||
let actual = ConnectionProfileGroup.getGroupFullNameParts(groupFullName);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
test('getGroupFullNameParts should return a list With ROOT in it given null', () => {
|
||||
let groupFullName: string = undefined;
|
||||
let expected: string[] = [ConnectionProfileGroup.RootGroupName];
|
||||
let actual = ConnectionProfileGroup.getGroupFullNameParts(groupFullName);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
test('getGroupFullNameParts should return a list With ROOT in it given /', () => {
|
||||
let groupFullName: string = '/';
|
||||
let expected: string[] = [ConnectionProfileGroup.RootGroupName];
|
||||
let actual = ConnectionProfileGroup.getGroupFullNameParts(groupFullName);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
test('getGroupFullNameParts should add ROOT as first item if not added already and string starts with /', () => {
|
||||
let groupFullName: string = '/Groups/Group1';
|
||||
let expected: string[] = [ConnectionProfileGroup.RootGroupName, 'Groups', 'Group1'];
|
||||
let actual = ConnectionProfileGroup.getGroupFullNameParts(groupFullName);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
test('getGroupFullNameParts should add ROOT as first item if not added already', () => {
|
||||
let groupFullName: string = 'Groups/Group1';
|
||||
let expected: string[] = [ConnectionProfileGroup.RootGroupName, 'Groups', 'Group1'];
|
||||
let actual = ConnectionProfileGroup.getGroupFullNameParts(groupFullName);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
test('getGroupFullNameParts should not add ROOT if already added and string starts with /', () => {
|
||||
let groupFullName: string = '/ROOT/Groups/Group1';
|
||||
let expected: string[] = [ConnectionProfileGroup.RootGroupName, 'Groups', 'Group1'];
|
||||
let actual = ConnectionProfileGroup.getGroupFullNameParts(groupFullName);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
test('getGroupFullNameParts should not add ROOT if already added', () => {
|
||||
let groupFullName: string = 'ROOT/Groups/Group1';
|
||||
let expected: string[] = [ConnectionProfileGroup.RootGroupName, 'Groups', 'Group1'];
|
||||
let actual = ConnectionProfileGroup.getGroupFullNameParts(groupFullName);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
test('getGroupFullNameParts should not add ROOT if already added and it is not uppercase', () => {
|
||||
let groupFullName: string = 'rOOT/Groups/Group1';
|
||||
let expected: string[] = [ConnectionProfileGroup.RootGroupName, 'Groups', 'Group1'];
|
||||
let actual = ConnectionProfileGroup.getGroupFullNameParts(groupFullName);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
test('isRoot should return true given empty string', () => {
|
||||
let name: string = '';
|
||||
let expected: boolean = true;
|
||||
let actual = ConnectionProfileGroup.isRoot(name);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
test('isRoot should return true given null', () => {
|
||||
let name: string = undefined;
|
||||
let expected: boolean = true;
|
||||
let actual = ConnectionProfileGroup.isRoot(name);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
test('isRoot should return true given /', () => {
|
||||
let name: string = '/';
|
||||
let expected: boolean = true;
|
||||
let actual = ConnectionProfileGroup.isRoot(name);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
test('isRoot should return true given root', () => {
|
||||
let name: string = 'root';
|
||||
let expected: boolean = true;
|
||||
let actual = ConnectionProfileGroup.isRoot(name);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
test('sameGroupName should return true given root', () => {
|
||||
let name1: string = '/';
|
||||
let name2: string = '';
|
||||
let expected: boolean = true;
|
||||
let actual = ConnectionProfileGroup.sameGroupName(name1, name2);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
test('sameGroupName should return true given same group names', () => {
|
||||
let name1: string = '/group1';
|
||||
let name2: string = '/Group1';
|
||||
let expected: boolean = true;
|
||||
let actual = ConnectionProfileGroup.sameGroupName(name1, name2);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
test('sameGroupName should return false given two different groups', () => {
|
||||
let name1: string = '/';
|
||||
let name2: string = '/Group1';
|
||||
let expected: boolean = false;
|
||||
let actual = ConnectionProfileGroup.sameGroupName(name1, name2);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
});
|
||||
239
src/sqltest/parts/connection/connectionStatusManager.test.ts
Normal file
239
src/sqltest/parts/connection/connectionStatusManager.test.ts
Normal file
@@ -0,0 +1,239 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import data = require('data');
|
||||
import { ConnectionStatusManager } from 'sql/parts/connection/common/connectionStatusManager';
|
||||
import * as Utils from 'sql/parts/connection/common/utils';
|
||||
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
||||
import { CapabilitiesTestService } from 'sqltest/stubs/capabilitiesTestService';
|
||||
import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
|
||||
|
||||
let connections: ConnectionStatusManager;
|
||||
let capabilitiesService: CapabilitiesTestService;
|
||||
let connectionProfileObject: ConnectionProfile;
|
||||
let connectionProfile: IConnectionProfile = {
|
||||
serverName: 'new server',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g2/g2-2',
|
||||
groupId: 'group id',
|
||||
getOptionsKey: () => 'connection1',
|
||||
matches: undefined,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: undefined
|
||||
};
|
||||
let editorConnectionProfile: IConnectionProfile = {
|
||||
serverName: 'new server',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g2/g2-2',
|
||||
groupId: 'group id',
|
||||
getOptionsKey: () => 'connection2',
|
||||
matches: undefined,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: undefined
|
||||
};
|
||||
let connectionProfileWithoutDbName: IConnectionProfile = {
|
||||
serverName: 'new server',
|
||||
databaseName: '',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g2/g2-2',
|
||||
groupId: 'group id',
|
||||
getOptionsKey: () => 'connection1',
|
||||
matches: undefined,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: undefined
|
||||
};
|
||||
|
||||
let connection1Id: string;
|
||||
let connection2Id: string;
|
||||
let connection3Id: string;
|
||||
|
||||
suite('SQL ConnectionStatusManager tests', () => {
|
||||
setup(() => {
|
||||
capabilitiesService = new CapabilitiesTestService();
|
||||
connectionProfileObject = new ConnectionProfile(capabilitiesService.getCapabilities().find(x => x.providerName === 'MSSQL')
|
||||
, connectionProfile);
|
||||
connections = new ConnectionStatusManager(capabilitiesService);
|
||||
connection1Id = Utils.generateUri(connectionProfile);
|
||||
connection2Id = 'connection2Id';
|
||||
connection3Id = 'connection3Id';
|
||||
connections.addConnection(connectionProfile, connection1Id);
|
||||
connections.addConnection(editorConnectionProfile, connection2Id);
|
||||
connections.addConnection(connectionProfileWithoutDbName, connection3Id);
|
||||
});
|
||||
|
||||
test('findConnection should return undefined given invalid id', () => {
|
||||
let id: string = 'invalid id';
|
||||
let expected = undefined;
|
||||
let actual = connections.findConnection(id);
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
test('findConnection should return connection given valid id', () => {
|
||||
let id: string = connection1Id;
|
||||
let expected = connectionProfileObject;
|
||||
let actual = connections.findConnection(id);
|
||||
assert.deepEqual(actual.connectionProfile, expected);
|
||||
});
|
||||
|
||||
test('getConnectionProfile should return undefined given invalid id', () => {
|
||||
let id: string = 'invalid id';
|
||||
let expected = undefined;
|
||||
let actual = connections.getConnectionProfile(id);
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
test('getConnectionProfile should return connection given valid id', () => {
|
||||
let id: string = connection1Id;
|
||||
let expected = connectionProfileObject;
|
||||
let actual = connections.getConnectionProfile(id);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
test('hasConnection should return false given invalid id', () => {
|
||||
let id: string = 'invalid id';
|
||||
let expected = false;
|
||||
let actual = connections.hasConnection(id);
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
test('hasConnection should return true given valid id', () => {
|
||||
let id: string = connection1Id;
|
||||
let expected = true;
|
||||
let actual = connections.hasConnection(id);
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
test('addConnection should set connecting to true', () => {
|
||||
let expected = true;
|
||||
let summary: data.ConnectionInfoSummary = {
|
||||
ownerUri: connection1Id,
|
||||
connectionId: connection1Id,
|
||||
messages: undefined,
|
||||
errorMessage: undefined,
|
||||
errorNumber: undefined,
|
||||
serverInfo: undefined,
|
||||
connectionSummary: undefined
|
||||
};
|
||||
connections.onConnectionComplete(summary);
|
||||
let actual = connections.addConnection(connectionProfile, connection1Id).connecting;
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
test('onConnectionComplete should set connecting to false', () => {
|
||||
let expected = false;
|
||||
let summary: data.ConnectionInfoSummary = {
|
||||
ownerUri: connection1Id,
|
||||
connectionId: connection1Id,
|
||||
messages: undefined,
|
||||
errorMessage: undefined,
|
||||
errorNumber: undefined,
|
||||
serverInfo: undefined,
|
||||
connectionSummary: undefined
|
||||
};
|
||||
connections.onConnectionComplete(summary);
|
||||
let actual = connections.findConnection(connection1Id).connecting;
|
||||
assert.equal(actual, expected);
|
||||
actual = connections.isConnecting(connection1Id);
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
test('updateConnection should update the connection info', () => {
|
||||
let expected = connectionProfile.groupId + '1';
|
||||
let expectedConnectionId = 'new id';
|
||||
connections.addConnection(connectionProfile, connection1Id);
|
||||
|
||||
let updatedConnection = Object.assign({}, connectionProfile, { groupId: expected, getOptionsKey: () => connectionProfile.getOptionsKey() + expected, id: expectedConnectionId });
|
||||
let actualId = connections.updateConnectionProfile(updatedConnection, connection1Id);
|
||||
|
||||
let newId = Utils.generateUri(updatedConnection);
|
||||
let actual = connections.getConnectionProfile(newId).groupId;
|
||||
let actualConnectionId = connections.getConnectionProfile(newId).id;
|
||||
assert.equal(actual, expected);
|
||||
assert.equal(actualId, newId);
|
||||
assert.equal(actualConnectionId, expectedConnectionId);
|
||||
});
|
||||
|
||||
test('updateDatabaseName should update the database name in connection', () => {
|
||||
let dbName: string = 'db name';
|
||||
let summary: data.ConnectionInfoSummary = {
|
||||
connectionSummary: {
|
||||
databaseName: dbName,
|
||||
serverName: undefined,
|
||||
userName: undefined
|
||||
}
|
||||
, ownerUri: connection3Id,
|
||||
connectionId: 'connection id',
|
||||
errorMessage: undefined,
|
||||
errorNumber: undefined,
|
||||
messages: undefined,
|
||||
serverInfo: undefined
|
||||
};
|
||||
|
||||
//The original connection didn't have database name
|
||||
let connectionStatus = connections.findConnection(connection3Id);
|
||||
connectionStatus.connectionProfile.databaseName = '';
|
||||
|
||||
//Verify database name changed after connection is complete
|
||||
connections.updateDatabaseName(summary);
|
||||
connectionStatus = connections.findConnection(connection3Id);
|
||||
assert.equal(connectionStatus.connectionProfile.databaseName, dbName);
|
||||
});
|
||||
|
||||
test('getOriginalOwnerUri should return the original uri given uri with db name', () => {
|
||||
let dbName: string = 'db name';
|
||||
let summary: data.ConnectionInfoSummary = {
|
||||
connectionSummary: {
|
||||
databaseName: dbName,
|
||||
serverName: undefined,
|
||||
userName: undefined
|
||||
}
|
||||
, ownerUri: connection3Id,
|
||||
connectionId: 'connection id',
|
||||
errorMessage: undefined,
|
||||
errorNumber: undefined,
|
||||
messages: undefined,
|
||||
serverInfo: undefined
|
||||
};
|
||||
|
||||
//The original connection didn't have database name
|
||||
let connectionStatus = connections.findConnection(connection3Id);
|
||||
connectionStatus.connectionProfile.databaseName = '';
|
||||
|
||||
//Verify database name changed after connection is complete
|
||||
connections.updateDatabaseName(summary);
|
||||
connectionStatus = connections.findConnection(connection3Id);
|
||||
let ownerUriWithDbName = Utils.generateUriWithPrefix(connectionStatus.connectionProfile, 'connection://');
|
||||
|
||||
//The uri assigned to connection without db name should be the original one
|
||||
let connectionWitDbStatus = connections.getOriginalOwnerUri(ownerUriWithDbName);
|
||||
assert.equal(connectionWitDbStatus, connection3Id);
|
||||
});
|
||||
|
||||
test('getOriginalOwnerUri should return given uri if the original uri is the same as the given uri', () => {
|
||||
|
||||
let connectionStatus = connections.getOriginalOwnerUri(connection2Id);
|
||||
assert.equal(connectionStatus, connection2Id);
|
||||
});
|
||||
});
|
||||
459
src/sqltest/parts/connection/connectionStore.test.ts
Normal file
459
src/sqltest/parts/connection/connectionStore.test.ts
Normal file
@@ -0,0 +1,459 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as TypeMoq from 'typemoq';
|
||||
import { ConnectionConfig } from 'sql/parts/connection/common/connectionConfig';
|
||||
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
||||
import { WorkspaceConfigurationTestService } from 'sqltest/stubs/workspaceConfigurationTestService';
|
||||
import * as Constants from 'sql/parts/connection/common/constants';
|
||||
import { StorageTestService } from 'sqltest/stubs/storageTestService';
|
||||
import { ConnectionStore } from 'sql/parts/connection/common/connectionStore';
|
||||
import { CredentialsService } from 'sql/services/credentials/credentialsService';
|
||||
import * as assert from 'assert';
|
||||
import { Memento } from 'vs/workbench/common/memento';
|
||||
import { CapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
|
||||
import * as data from 'data';
|
||||
import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { IConnectionProfileGroup } from 'sql/parts/connection/common/connectionProfileGroup';
|
||||
|
||||
suite('SQL ConnectionStore tests', () => {
|
||||
let defaultNamedProfile: IConnectionProfile;
|
||||
let defaultUnnamedProfile: IConnectionProfile;
|
||||
let context: TypeMoq.Mock<Memento>;
|
||||
let credentialStore: TypeMoq.Mock<CredentialsService>;
|
||||
let connectionConfig: TypeMoq.Mock<ConnectionConfig>;
|
||||
let workspaceConfigurationServiceMock: TypeMoq.Mock<WorkspaceConfigurationTestService>;
|
||||
let storageServiceMock: TypeMoq.Mock<StorageTestService>;
|
||||
let capabilitiesService: TypeMoq.Mock<CapabilitiesService>;
|
||||
let mementoArray: any = [];
|
||||
let maxRecent = 5;
|
||||
let msSQLCapabilities: data.DataProtocolServerCapabilities;
|
||||
let defaultNamedConnectionProfile: ConnectionProfile;
|
||||
let onProviderRegistered = new Emitter<data.DataProtocolServerCapabilities>();
|
||||
|
||||
|
||||
setup(() => {
|
||||
defaultNamedProfile = Object.assign({}, {
|
||||
serverName: 'namedServer',
|
||||
databaseName: 'bcd',
|
||||
authenticationType: 'SqlLogin',
|
||||
userName: 'cde',
|
||||
password: 'asdf!@#$',
|
||||
savePassword: true,
|
||||
groupId: '',
|
||||
groupFullName: '',
|
||||
getOptionsKey: undefined,
|
||||
matches: undefined,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: undefined
|
||||
});
|
||||
|
||||
defaultUnnamedProfile = Object.assign({}, {
|
||||
serverName: 'unnamedServer',
|
||||
databaseName: undefined,
|
||||
authenticationType: 'SqlLogin',
|
||||
userName: 'aUser',
|
||||
password: 'asdf!@#$',
|
||||
savePassword: true,
|
||||
groupId: '',
|
||||
groupFullName: '',
|
||||
getOptionsKey: undefined,
|
||||
matches: undefined,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: undefined
|
||||
});
|
||||
|
||||
let momento = new Memento('ConnectionManagement');
|
||||
context = TypeMoq.Mock.ofInstance(momento);
|
||||
context.setup(x => x.getMemento(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => mementoArray);
|
||||
|
||||
credentialStore = TypeMoq.Mock.ofType(CredentialsService);
|
||||
connectionConfig = TypeMoq.Mock.ofType(ConnectionConfig);
|
||||
|
||||
// setup configuration to return maxRecent for the #MRU items
|
||||
|
||||
let configResult: { [key: string]: any } = {};
|
||||
configResult[Constants.configMaxRecentConnections] = maxRecent;
|
||||
|
||||
workspaceConfigurationServiceMock = TypeMoq.Mock.ofType(WorkspaceConfigurationTestService);
|
||||
workspaceConfigurationServiceMock.setup(x => x.getConfiguration(Constants.sqlConfigSectionName))
|
||||
.returns(() => configResult);
|
||||
|
||||
storageServiceMock = TypeMoq.Mock.ofType(StorageTestService);
|
||||
|
||||
capabilitiesService = TypeMoq.Mock.ofType(CapabilitiesService);
|
||||
let capabilities: data.DataProtocolServerCapabilities[] = [];
|
||||
let connectionProvider: data.ConnectionProviderOptions = {
|
||||
options: [
|
||||
{
|
||||
name: 'serverName',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 0,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'databaseName',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 1,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'userName',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 3,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'authenticationType',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 2,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'password',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 4,
|
||||
valueType: 0
|
||||
}
|
||||
]
|
||||
};
|
||||
msSQLCapabilities = {
|
||||
protocolVersion: '1',
|
||||
providerName: 'MSSQL',
|
||||
providerDisplayName: 'MSSQL',
|
||||
connectionProvider: connectionProvider,
|
||||
adminServicesProvider: undefined,
|
||||
features: undefined
|
||||
};
|
||||
capabilities.push(msSQLCapabilities);
|
||||
capabilitiesService.setup(x => x.getCapabilities()).returns(() => capabilities);
|
||||
capabilitiesService.setup(x => x.onProviderRegisteredEvent).returns(() => onProviderRegistered.event);
|
||||
connectionConfig.setup(x => x.getCapabilities('MSSQL')).returns(() => msSQLCapabilities);
|
||||
let groups: IConnectionProfileGroup[] = [
|
||||
{
|
||||
id: 'root',
|
||||
name: 'root',
|
||||
parentId: '',
|
||||
color: '',
|
||||
description: ''
|
||||
},
|
||||
{
|
||||
id: 'g1',
|
||||
name: 'g1',
|
||||
parentId: 'root',
|
||||
color: 'blue',
|
||||
description: 'g1'
|
||||
}
|
||||
];
|
||||
connectionConfig.setup(x => x.getAllGroups()).returns(() => groups);
|
||||
|
||||
defaultNamedConnectionProfile = new ConnectionProfile(msSQLCapabilities, defaultNamedProfile);
|
||||
});
|
||||
|
||||
test('addActiveConnection should limit recent connection saves to the MaxRecentConnections amount', (done) => {
|
||||
// Given 5 is the max # creds
|
||||
let numCreds = 6;
|
||||
|
||||
// setup memento for MRU to return a list we have access to
|
||||
credentialStore.setup(x => x.saveCredential(TypeMoq.It.isAny(), TypeMoq.It.isAny()))
|
||||
.returns(() => Promise.resolve(true));
|
||||
|
||||
// When saving 4 connections
|
||||
// Expect all of them to be saved even if size is limited to 3
|
||||
let connectionStore = new ConnectionStore(storageServiceMock.object, context.object, undefined, workspaceConfigurationServiceMock.object,
|
||||
credentialStore.object, capabilitiesService.object, connectionConfig.object);
|
||||
let promise = Promise.resolve();
|
||||
for (let i = 0; i < numCreds; i++) {
|
||||
let cred = Object.assign({}, defaultNamedProfile, { serverName: defaultNamedProfile.serverName + i });
|
||||
let connectionProfile = new ConnectionProfile(msSQLCapabilities, cred);
|
||||
promise = promise.then(() => {
|
||||
return connectionStore.addActiveConnection(connectionProfile);
|
||||
}).then(() => {
|
||||
let current = connectionStore.getRecentlyUsedConnections();
|
||||
if (i >= maxRecent) {
|
||||
assert.equal(current.length, maxRecent, `expect only top ${maxRecent} creds to be saved`);
|
||||
} else {
|
||||
assert.equal(current.length, i + 1, `expect all credentials to be saved ${current.length}|${i + 1} `);
|
||||
}
|
||||
assert.equal(current[0].serverName, cred.serverName, 'Expect most recently saved item to be first in list');
|
||||
assert.ok(!current[0].password);
|
||||
});
|
||||
}
|
||||
promise.then(() => {
|
||||
credentialStore.verify(x => x.saveCredential(TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.exactly(numCreds));
|
||||
let recentConnections = connectionStore.getActiveConnections();
|
||||
assert.equal(numCreds, recentConnections.length, `expect number of active connection ${numCreds}|${recentConnections.length} `);
|
||||
done();
|
||||
}, err => {
|
||||
// Must call done here so test indicates it's finished if errors occur
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
test('addActiveConnection should add same connection exactly once', (done) => {
|
||||
// setup memento for MRU to return a list we have access to
|
||||
credentialStore.setup(x => x.saveCredential(TypeMoq.It.isAny(), TypeMoq.It.isAny()))
|
||||
.returns(() => Promise.resolve(true));
|
||||
|
||||
// Given we save the same connection twice
|
||||
// Then expect the only 1 instance of that connection to be listed in the MRU
|
||||
let connectionStore = new ConnectionStore(storageServiceMock.object, context.object, undefined, workspaceConfigurationServiceMock.object,
|
||||
credentialStore.object, capabilitiesService.object, connectionConfig.object);
|
||||
connectionStore.clearActiveConnections();
|
||||
connectionStore.clearRecentlyUsed();
|
||||
let promise = Promise.resolve();
|
||||
let cred = Object.assign({}, defaultNamedProfile, { serverName: defaultNamedProfile.serverName + 1 });
|
||||
let connectionProfile = new ConnectionProfile(msSQLCapabilities, cred);
|
||||
promise = promise.then(() => {
|
||||
return connectionStore.addActiveConnection(defaultNamedConnectionProfile);
|
||||
}).then(() => {
|
||||
return connectionStore.addActiveConnection(connectionProfile);
|
||||
}).then(() => {
|
||||
return connectionStore.addActiveConnection(connectionProfile);
|
||||
}).then(() => {
|
||||
let current = connectionStore.getRecentlyUsedConnections();
|
||||
assert.equal(current.length, 2, 'expect 2 unique credentials to have been added');
|
||||
assert.equal(current[0].serverName, cred.serverName, 'Expect most recently saved item to be first in list');
|
||||
assert.ok(!current[0].password);
|
||||
}).then(() => done(), err => done(err));
|
||||
});
|
||||
|
||||
test('addActiveConnection should save password to credential store', (done) => {
|
||||
|
||||
// Setup credential store to capture credentials sent to it
|
||||
let capturedCreds: any;
|
||||
credentialStore.setup(x => x.saveCredential(TypeMoq.It.isAny(), TypeMoq.It.isAny()))
|
||||
.callback((cred: string, pass: any) => {
|
||||
capturedCreds = {
|
||||
'credentialId': cred,
|
||||
'password': pass
|
||||
};
|
||||
})
|
||||
.returns(() => Promise.resolve(true));
|
||||
|
||||
// Given we save 1 connection with password and multiple other connections without
|
||||
let connectionStore = new ConnectionStore(storageServiceMock.object, context.object, undefined, workspaceConfigurationServiceMock.object,
|
||||
credentialStore.object, capabilitiesService.object, connectionConfig.object);
|
||||
connectionStore.clearActiveConnections();
|
||||
connectionStore.clearRecentlyUsed();
|
||||
let integratedCred = Object.assign({}, defaultNamedProfile, {
|
||||
serverName: defaultNamedProfile.serverName + 'Integrated',
|
||||
authenticationType: 'Integrated',
|
||||
userName: '',
|
||||
password: ''
|
||||
});
|
||||
let noPwdCred = Object.assign({}, defaultNamedProfile, {
|
||||
serverName: defaultNamedProfile.serverName + 'NoPwd',
|
||||
password: ''
|
||||
});
|
||||
let connectionProfile = new ConnectionProfile(msSQLCapabilities, defaultNamedProfile);
|
||||
|
||||
let expectedCredCount = 0;
|
||||
let promise = Promise.resolve();
|
||||
promise = promise.then(() => {
|
||||
expectedCredCount++;
|
||||
return connectionStore.addActiveConnection(connectionProfile);
|
||||
}).then(() => {
|
||||
let current = connectionStore.getRecentlyUsedConnections();
|
||||
// Then verify that since its password based we save the password
|
||||
credentialStore.verify(x => x.saveCredential(TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||
assert.strictEqual(capturedCreds.password, defaultNamedProfile.password);
|
||||
let credId: string = capturedCreds.credentialId;
|
||||
assert.ok(credId.includes(ConnectionStore.CRED_PROFILE_USER), 'Expect credential to be marked as an Profile cred');
|
||||
assert.ok(!current[0].password);
|
||||
}).then(() => {
|
||||
// When add integrated auth connection
|
||||
expectedCredCount++;
|
||||
let integratedCredConnectionProfile = new ConnectionProfile(msSQLCapabilities, integratedCred);
|
||||
return connectionStore.addActiveConnection(integratedCredConnectionProfile);
|
||||
}).then(() => {
|
||||
let current = connectionStore.getRecentlyUsedConnections();
|
||||
// then expect no to have credential store called, but MRU count upped to 2
|
||||
credentialStore.verify(x => x.saveCredential(TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||
assert.equal(current.length, expectedCredCount, `expect ${expectedCredCount} unique credentials to have been added`);
|
||||
}).then(() => {
|
||||
// When add connection without password
|
||||
expectedCredCount++;
|
||||
let noPwdCredConnectionProfile = new ConnectionProfile(msSQLCapabilities, noPwdCred);
|
||||
return connectionStore.addActiveConnection(noPwdCredConnectionProfile);
|
||||
}).then(() => {
|
||||
let current = connectionStore.getRecentlyUsedConnections();
|
||||
// then expect no to have credential store called, but MRU count upped to 3
|
||||
credentialStore.verify(x => x.saveCredential(TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||
assert.equal(current.length, expectedCredCount, `expect ${expectedCredCount} unique credentials to have been added`);
|
||||
}).then(() => done(), err => done(err));
|
||||
});
|
||||
|
||||
test('can clear connections list', (done) => {
|
||||
connectionConfig.setup(x => x.getConnections(TypeMoq.It.isAny())).returns(() => []);
|
||||
|
||||
let connectionStore = new ConnectionStore(storageServiceMock.object, context.object, undefined, workspaceConfigurationServiceMock.object,
|
||||
credentialStore.object, capabilitiesService.object, connectionConfig.object);
|
||||
|
||||
// When we clear the connections list and get the list of available connection items
|
||||
connectionStore.clearActiveConnections();
|
||||
connectionStore.clearRecentlyUsed();
|
||||
// Expect no connection items
|
||||
let result = connectionStore.getActiveConnections();
|
||||
let expectedCount = 0; // 1 for create connection profile
|
||||
assert.equal(result.length, expectedCount);
|
||||
result = connectionStore.getRecentlyUsedConnections();
|
||||
assert.equal(result.length, expectedCount);
|
||||
// Then test is complete
|
||||
done();
|
||||
});
|
||||
|
||||
test('isPasswordRequired should return true for MSSQL SqlLogin', () => {
|
||||
|
||||
let connectionStore = new ConnectionStore(storageServiceMock.object, context.object, undefined, workspaceConfigurationServiceMock.object,
|
||||
credentialStore.object, capabilitiesService.object, connectionConfig.object);
|
||||
|
||||
let expected: boolean = true;
|
||||
let actual = connectionStore.isPasswordRequired(defaultNamedProfile);
|
||||
|
||||
assert.equal(expected, actual);
|
||||
});
|
||||
|
||||
test('isPasswordRequired should return true for MSSQL SqlLogin for connection profile object', () => {
|
||||
let connectionStore = new ConnectionStore(storageServiceMock.object, context.object, undefined, workspaceConfigurationServiceMock.object,
|
||||
credentialStore.object, capabilitiesService.object, connectionConfig.object);
|
||||
let connectionProfile = new ConnectionProfile(msSQLCapabilities, defaultNamedProfile);
|
||||
let expected: boolean = true;
|
||||
let actual = connectionStore.isPasswordRequired(connectionProfile);
|
||||
|
||||
assert.equal(expected, actual);
|
||||
});
|
||||
|
||||
test('isPasswordRequired should return false if the password is not required in capabilities', () => {
|
||||
let providerName: string = 'providername';
|
||||
let connectionProvider: data.ConnectionProviderOptions = {
|
||||
options: msSQLCapabilities.connectionProvider.options.map(o => {
|
||||
if (o.name === 'password') {
|
||||
o.isRequired = false;
|
||||
}
|
||||
return o;
|
||||
})
|
||||
};
|
||||
let providerCapabilities = {
|
||||
protocolVersion: '1',
|
||||
providerName: providerName,
|
||||
providerDisplayName: providerName,
|
||||
connectionProvider: connectionProvider,
|
||||
adminServicesProvider: undefined,
|
||||
features: undefined
|
||||
};
|
||||
connectionConfig.setup(x => x.getCapabilities(providerName)).returns(() => providerCapabilities);
|
||||
|
||||
let connectionStore = new ConnectionStore(storageServiceMock.object, context.object, undefined, workspaceConfigurationServiceMock.object,
|
||||
credentialStore.object, capabilitiesService.object, connectionConfig.object);
|
||||
let connectionProfile: IConnectionProfile = Object.assign({}, defaultNamedProfile, { providerName: providerName });
|
||||
let expected: boolean = false;
|
||||
let actual = connectionStore.isPasswordRequired(connectionProfile);
|
||||
|
||||
assert.equal(expected, actual);
|
||||
});
|
||||
|
||||
test('saveProfile should save the password after the profile is saved', done => {
|
||||
let password: string = 'asdf!@#$';
|
||||
let groupId: string = 'group id';
|
||||
let connectionProfile: IConnectionProfile = Object.assign({}, defaultNamedProfile, { password: password });
|
||||
let savedConnection: IConnectionProfile = Object.assign({}, connectionProfile, { groupId: groupId, password: '' });
|
||||
connectionConfig.setup(x => x.addConnection(TypeMoq.It.isAny())).returns(() => Promise.resolve(savedConnection));
|
||||
credentialStore.setup(x => x.saveCredential(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => Promise.resolve(true));
|
||||
|
||||
let connectionStore = new ConnectionStore(storageServiceMock.object, context.object, undefined, workspaceConfigurationServiceMock.object,
|
||||
credentialStore.object, capabilitiesService.object, connectionConfig.object);
|
||||
|
||||
connectionStore.saveProfile(connectionProfile).then(profile => {
|
||||
// add connection should be called with a profile without password
|
||||
connectionConfig.verify(x => x.addConnection(TypeMoq.It.is<IConnectionProfile>(c => c.password === '')), TypeMoq.Times.once());
|
||||
credentialStore.verify(x => x.saveCredential(TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||
assert.equal(profile.password, password, 'The returned profile should still keep the password');
|
||||
assert.equal(profile.groupId, groupId, 'Group id should be set in the profile');
|
||||
done();
|
||||
}).catch(err => {
|
||||
assert.fail(err);
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
test('addConnectionToMemento should not add duplicate items', () => {
|
||||
let connectionStore = new ConnectionStore(storageServiceMock.object, context.object, undefined, workspaceConfigurationServiceMock.object,
|
||||
credentialStore.object, capabilitiesService.object, connectionConfig.object);
|
||||
let mementoKey = 'RECENT_CONNECTIONS2';
|
||||
connectionStore.clearFromMemento(mementoKey);
|
||||
let connectionProfile: IConnectionProfile = Object.assign({}, defaultNamedProfile);
|
||||
connectionStore.addConnectionToMemento(connectionProfile, mementoKey);
|
||||
|
||||
connectionProfile = Object.assign({}, defaultNamedProfile, { authenticationType: 'Integrated', userName: '' });
|
||||
connectionStore.addConnectionToMemento(connectionProfile, mementoKey);
|
||||
|
||||
let currentList = connectionStore.getConnectionsFromMemento(mementoKey);
|
||||
assert.equal(currentList.length, 2, 'Adding same connection with different auth');
|
||||
|
||||
connectionProfile = Object.assign({}, defaultNamedProfile, { groupFullName: 'new group' });
|
||||
connectionStore.addConnectionToMemento(connectionProfile, mementoKey);
|
||||
|
||||
currentList = connectionStore.getConnectionsFromMemento(mementoKey);
|
||||
assert.equal(currentList.length, 3, 'Adding same connection with different group name');
|
||||
|
||||
connectionProfile = Object.assign({}, defaultNamedProfile,
|
||||
{ groupFullName: defaultNamedProfile.groupFullName.toUpperCase() });
|
||||
connectionStore.addConnectionToMemento(connectionProfile, mementoKey);
|
||||
|
||||
currentList = connectionStore.getConnectionsFromMemento(mementoKey);
|
||||
assert.equal(currentList.length, 3, 'Adding same connection with same group name but uppercase');
|
||||
|
||||
connectionProfile = Object.assign({}, defaultNamedProfile,
|
||||
{ groupFullName: '' });
|
||||
connectionStore.addConnectionToMemento(connectionProfile, mementoKey);
|
||||
|
||||
currentList = connectionStore.getConnectionsFromMemento(mementoKey);
|
||||
assert.equal(currentList.length, 3, 'Adding same connection with group empty string');
|
||||
|
||||
connectionProfile = Object.assign({}, defaultNamedProfile,
|
||||
{ groupFullName: '/' });
|
||||
connectionStore.addConnectionToMemento(connectionProfile, mementoKey);
|
||||
|
||||
currentList = connectionStore.getConnectionsFromMemento(mementoKey);
|
||||
assert.equal(currentList.length, 3, 'Adding same connection with group /');
|
||||
});
|
||||
});
|
||||
516
src/sqltest/parts/connection/connectionTreeActions.test.ts
Normal file
516
src/sqltest/parts/connection/connectionTreeActions.test.ts
Normal file
@@ -0,0 +1,516 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import * as TypeMoq from 'typemoq';
|
||||
import * as assert from 'assert';
|
||||
import { ConnectionProfileGroup } from 'sql/parts/connection/common/connectionProfileGroup';
|
||||
import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
|
||||
import {
|
||||
RefreshAction, AddServerAction, DeleteConnectionAction, DisconnectConnectionAction,
|
||||
ActiveConnectionsFilterAction, RecentConnectionsFilterAction
|
||||
}
|
||||
from 'sql/parts/registeredServer/viewlet/connectionTreeAction';
|
||||
import { TestConnectionManagementService } from 'sqltest/stubs/connectionManagementService.test';
|
||||
import { ErrorMessageServiceStub } from 'sqltest/stubs/errorMessageServiceStub';
|
||||
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
|
||||
import { ServerTreeView } from 'sql/parts/registeredServer/viewlet/serverTreeView';
|
||||
import * as Constants from 'sql/parts/connection/common/constants';
|
||||
import * as LocalizedConstants from 'sql/parts/connection/common/localizedConstants';
|
||||
import { ObjectExplorerService, ObjectExplorerNodeEventArgs } from 'sql/parts/registeredServer/common/objectExplorerService';
|
||||
import { TreeNode } from 'sql/parts/registeredServer/common/treeNode';
|
||||
import { NodeType } from 'sql/parts/registeredServer/common/nodeType';
|
||||
import { Tree } from 'vs/base/parts/tree/browser/treeImpl';
|
||||
import { ServerTreeDataSource } from 'sql/parts/registeredServer/viewlet/serverTreeDataSource';
|
||||
import { Builder, $ } from 'vs/base/browser/builder';
|
||||
import WinJS = require('vs/base/common/winjs.base');
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { ObjectExplorerActionsContext, ManageConnectionAction } from 'sql/parts/registeredServer/viewlet/objectExplorerActions';
|
||||
import { IConnectionResult, IConnectionParams } from 'sql/parts/connection/common/connectionManagement';
|
||||
import { TreeSelectionHandler } from 'sql/parts/registeredServer/viewlet/treeSelectionHandler';
|
||||
|
||||
suite('SQL Connection Tree Action tests', () => {
|
||||
let errorMessageService: TypeMoq.Mock<ErrorMessageServiceStub>;
|
||||
let connectionResult: IConnectionResult = {
|
||||
connected: true,
|
||||
errorMessage: undefined,
|
||||
errorCode: undefined
|
||||
};
|
||||
setup(() => {
|
||||
errorMessageService = TypeMoq.Mock.ofType(ErrorMessageServiceStub, TypeMoq.MockBehavior.Loose);
|
||||
let nothing: void;
|
||||
errorMessageService.setup(x => x.showDialog(Severity.Error, TypeMoq.It.isAnyString(), TypeMoq.It.isAnyString())).returns(() => nothing);
|
||||
});
|
||||
|
||||
function createConnectionManagementService(isConnectedReturnValue: boolean): TypeMoq.Mock<TestConnectionManagementService> {
|
||||
let connectionManagementService = TypeMoq.Mock.ofType(TestConnectionManagementService, TypeMoq.MockBehavior.Strict);
|
||||
connectionManagementService.callBase = true;
|
||||
connectionManagementService.setup(x => x.isConnected(undefined, TypeMoq.It.isAny())).returns(() => isConnectedReturnValue);
|
||||
connectionManagementService.setup(x => x.connect(TypeMoq.It.isAny(), undefined, TypeMoq.It.isAny(), undefined)).returns(() => Promise.resolve(connectionResult));
|
||||
connectionManagementService.setup(x => x.disconnect(TypeMoq.It.isAny())).returns(() => Promise.resolve(true));
|
||||
connectionManagementService.setup(x => x.findExistingConnection(TypeMoq.It.isAny())).returns(() => undefined);
|
||||
connectionManagementService.setup(x => x.showDashboard(TypeMoq.It.isAny())).returns(() => Promise.resolve(true));
|
||||
connectionManagementService.setup(x => x.isProfileConnected(TypeMoq.It.isAny())).returns(() => isConnectedReturnValue);
|
||||
connectionManagementService.setup(x => x.isProfileConnecting(TypeMoq.It.isAny())).returns(() => false);
|
||||
connectionManagementService.setup(x => x.showConnectionDialog(undefined, TypeMoq.It.isAny())).returns(() => new Promise<void>((resolve, reject) => resolve()));
|
||||
connectionManagementService.setup(x => x.onConnect).returns(() => new Emitter<IConnectionParams>().event);
|
||||
connectionManagementService.setup(x => x.onDisconnect).returns(() => new Emitter<any>().event);
|
||||
connectionManagementService.setup(x => x.deleteConnectionGroup(TypeMoq.It.isAny())).returns(() => Promise.resolve(true));
|
||||
connectionManagementService.setup(x => x.deleteConnection(TypeMoq.It.isAny())).returns(() => Promise.resolve(true));
|
||||
|
||||
return connectionManagementService;
|
||||
}
|
||||
|
||||
function createObjectExplorerService(connectionManagementService: TestConnectionManagementService): TypeMoq.Mock<ObjectExplorerService> {
|
||||
let objectExplorerService = TypeMoq.Mock.ofType(ObjectExplorerService, TypeMoq.MockBehavior.Strict, connectionManagementService);
|
||||
objectExplorerService.callBase = true;
|
||||
objectExplorerService.setup(x => x.getObjectExplorerNode(TypeMoq.It.isAny())).returns(() => new TreeNode('', '', false, '', '', '', undefined, undefined));
|
||||
objectExplorerService.setup(x => x.getObjectExplorerNode(undefined)).returns(() => new TreeNode('', '', false, '', '', '', undefined, undefined));
|
||||
objectExplorerService.setup(x => x.onUpdateObjectExplorerNodes).returns(() => new Emitter<ObjectExplorerNodeEventArgs>().event);
|
||||
|
||||
objectExplorerService.setup(x => x.onUpdateObjectExplorerNodes).returns(() => new Emitter<ObjectExplorerNodeEventArgs>().event);
|
||||
return objectExplorerService;
|
||||
}
|
||||
|
||||
test('ManageConnectionAction - test if connect is called for manage action if not already connected', (done) => {
|
||||
let isConnectedReturnValue: boolean = false;
|
||||
|
||||
let connectionManagementService = createConnectionManagementService(isConnectedReturnValue);
|
||||
let objectExplorerService = createObjectExplorerService(connectionManagementService.object);
|
||||
let treeSelectionMock = TypeMoq.Mock.ofType(TreeSelectionHandler);
|
||||
let instantiationService = TypeMoq.Mock.ofType(InstantiationService, TypeMoq.MockBehavior.Loose);
|
||||
instantiationService.setup(x => x.createInstance(TypeMoq.It.isAny())).returns((input) => {
|
||||
return treeSelectionMock.object;
|
||||
});
|
||||
|
||||
let manageConnectionAction: ManageConnectionAction = new ManageConnectionAction(ManageConnectionAction.ID,
|
||||
ManageConnectionAction.LABEL, connectionManagementService.object, instantiationService.object, objectExplorerService.object);
|
||||
let connection: ConnectionProfile = new ConnectionProfile(undefined, {
|
||||
savePassword: false,
|
||||
groupFullName: 'testGroup',
|
||||
serverName: 'testServerName',
|
||||
databaseName: 'testDatabaseName',
|
||||
authenticationType: 'integrated',
|
||||
password: 'test',
|
||||
userName: 'testUsername',
|
||||
groupId: undefined,
|
||||
getOptionsKey: undefined,
|
||||
matches: undefined,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: 'testId'
|
||||
});
|
||||
var actionContext = new ObjectExplorerActionsContext();
|
||||
actionContext.connectionProfile = connection;
|
||||
manageConnectionAction.run(actionContext).then((value) => {
|
||||
connectionManagementService.verify(x => x.connect(TypeMoq.It.isAny(), undefined, TypeMoq.It.isAny(), undefined), TypeMoq.Times.once());
|
||||
}).then(() => done(), (err) => done(err));
|
||||
});
|
||||
|
||||
test('ManageConnectionAction - test if connect is called for manage action on database node if not already connected', (done) => {
|
||||
let isConnectedReturnValue: boolean = false;
|
||||
let connectionManagementService = createConnectionManagementService(isConnectedReturnValue);
|
||||
let objectExplorerService = createObjectExplorerService(connectionManagementService.object);
|
||||
let treeSelectionMock = TypeMoq.Mock.ofType(TreeSelectionHandler);
|
||||
let instantiationService = TypeMoq.Mock.ofType(InstantiationService, TypeMoq.MockBehavior.Loose);
|
||||
instantiationService.setup(x => x.createInstance(TypeMoq.It.isAny())).returns((input) => {
|
||||
return treeSelectionMock.object;
|
||||
});
|
||||
|
||||
let manageConnectionAction: ManageConnectionAction = new ManageConnectionAction(ManageConnectionAction.ID,
|
||||
ManageConnectionAction.LABEL, connectionManagementService.object, instantiationService.object, objectExplorerService.object);
|
||||
let connection: ConnectionProfile = new ConnectionProfile(undefined, {
|
||||
savePassword: false,
|
||||
groupFullName: 'testGroup',
|
||||
serverName: 'testServerName',
|
||||
databaseName: 'testDatabaseName',
|
||||
authenticationType: 'integrated',
|
||||
password: 'test',
|
||||
userName: 'testUsername',
|
||||
groupId: undefined,
|
||||
getOptionsKey: undefined,
|
||||
matches: undefined,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: 'testId'
|
||||
});
|
||||
let treeNode = new TreeNode(NodeType.Database, 'db node', false, '', '', '', undefined, undefined);
|
||||
treeNode.connection = connection;
|
||||
var actionContext = new ObjectExplorerActionsContext();
|
||||
actionContext.treeNode = treeNode;
|
||||
manageConnectionAction.run(actionContext).then((value) => {
|
||||
connectionManagementService.verify(x => x.showDashboard(TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||
}).then(() => done(), (err) => done(err));
|
||||
});
|
||||
|
||||
|
||||
test('DisconnectConnectionAction - test if disconnect is called when profile is connected', (done) => {
|
||||
let isConnectedReturnValue: boolean = true;
|
||||
let connectionManagementService = createConnectionManagementService(isConnectedReturnValue);
|
||||
let objectExplorerService = createObjectExplorerService(connectionManagementService.object);
|
||||
|
||||
let changeConnectionAction: DisconnectConnectionAction = new DisconnectConnectionAction(DisconnectConnectionAction.ID, DisconnectConnectionAction.LABEL, connectionManagementService.object, objectExplorerService.object, errorMessageService.object);
|
||||
let connection: ConnectionProfile = new ConnectionProfile(undefined, {
|
||||
savePassword: false,
|
||||
groupFullName: 'testGroup',
|
||||
serverName: 'testServerName',
|
||||
databaseName: 'testDatabaseName',
|
||||
authenticationType: 'integrated',
|
||||
password: 'test',
|
||||
userName: 'testUsername',
|
||||
groupId: undefined,
|
||||
getOptionsKey: undefined,
|
||||
matches: undefined,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: 'testId'
|
||||
});
|
||||
var actionContext = new ObjectExplorerActionsContext();
|
||||
actionContext.connectionProfile = connection;
|
||||
changeConnectionAction.run(actionContext).then((value) => {
|
||||
connectionManagementService.verify(x => x.isProfileConnected(TypeMoq.It.isAny()), TypeMoq.Times.atLeastOnce());
|
||||
connectionManagementService.verify(x => x.disconnect(TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||
}).then(() => done(), (err) => done(err));
|
||||
});
|
||||
|
||||
test('AddServerAction - test if show connection dialog is called', (done) => {
|
||||
let connectionManagementService = createConnectionManagementService(true);
|
||||
|
||||
let connectionTreeAction: AddServerAction = new AddServerAction(AddServerAction.ID, AddServerAction.LABEL, connectionManagementService.object);
|
||||
let conProfGroup = new ConnectionProfileGroup('testGroup', undefined, 'testGroup', undefined, undefined);
|
||||
connectionTreeAction.run(conProfGroup).then((value) => {
|
||||
connectionManagementService.verify(x => x.showConnectionDialog(undefined, TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||
}).then(() => done(), (err) => done(err));
|
||||
});
|
||||
|
||||
test('ActiveConnectionsFilterAction - test if view is called to display filtered results', (done) => {
|
||||
let connectionManagementService = createConnectionManagementService(true);
|
||||
|
||||
let instantiationService = TypeMoq.Mock.ofType(InstantiationService, TypeMoq.MockBehavior.Loose);
|
||||
instantiationService.setup(x => x.createInstance(TypeMoq.It.isAny())).returns((input) => {
|
||||
return new TPromise((resolve) => resolve({}));
|
||||
});
|
||||
|
||||
let serverTreeView = TypeMoq.Mock.ofType(ServerTreeView, TypeMoq.MockBehavior.Strict, undefined, instantiationService.object, undefined, undefined, undefined);
|
||||
serverTreeView.setup(x => x.showFilteredTree(TypeMoq.It.isAnyString()));
|
||||
serverTreeView.setup(x => x.refreshTree());
|
||||
let connectionTreeAction: ActiveConnectionsFilterAction = new ActiveConnectionsFilterAction(ActiveConnectionsFilterAction.ID, ActiveConnectionsFilterAction.LABEL, serverTreeView.object, connectionManagementService.object);
|
||||
connectionTreeAction.run().then((value) => {
|
||||
serverTreeView.verify(x => x.showFilteredTree('active'), TypeMoq.Times.once());
|
||||
}).then(() => done(), (err) => done(err));
|
||||
});
|
||||
|
||||
test('ActiveConnectionsFilterAction - test if view is called refresh results if action is toggled', (done) => {
|
||||
let connectionManagementService = createConnectionManagementService(true);
|
||||
|
||||
let instantiationService = TypeMoq.Mock.ofType(InstantiationService, TypeMoq.MockBehavior.Loose);
|
||||
instantiationService.setup(x => x.createInstance(TypeMoq.It.isAny())).returns((input) => {
|
||||
return new TPromise((resolve) => resolve({}));
|
||||
});
|
||||
|
||||
let serverTreeView = TypeMoq.Mock.ofType(ServerTreeView, TypeMoq.MockBehavior.Strict, undefined, instantiationService.object, undefined, undefined, undefined);
|
||||
serverTreeView.setup(x => x.showFilteredTree(TypeMoq.It.isAnyString()));
|
||||
serverTreeView.setup(x => x.refreshTree());
|
||||
let connectionTreeAction: ActiveConnectionsFilterAction = new ActiveConnectionsFilterAction(ActiveConnectionsFilterAction.ID, ActiveConnectionsFilterAction.LABEL, serverTreeView.object, connectionManagementService.object);
|
||||
connectionTreeAction.isSet = true;
|
||||
connectionTreeAction.run().then((value) => {
|
||||
serverTreeView.verify(x => x.refreshTree(), TypeMoq.Times.once());
|
||||
}).then(() => done(), (err) => done(err));
|
||||
});
|
||||
|
||||
test('RecentConnectionsFilterAction - test if view is called to display filtered results', (done) => {
|
||||
let connectionManagementService = createConnectionManagementService(true);
|
||||
|
||||
let instantiationService = TypeMoq.Mock.ofType(InstantiationService, TypeMoq.MockBehavior.Loose);
|
||||
instantiationService.setup(x => x.createInstance(TypeMoq.It.isAny())).returns((input) => {
|
||||
return new TPromise((resolve) => resolve({}));
|
||||
});
|
||||
|
||||
let serverTreeView = TypeMoq.Mock.ofType(ServerTreeView, TypeMoq.MockBehavior.Strict, undefined, instantiationService.object, undefined, undefined, undefined);
|
||||
serverTreeView.setup(x => x.showFilteredTree(TypeMoq.It.isAnyString()));
|
||||
serverTreeView.setup(x => x.refreshTree());
|
||||
let connectionTreeAction: RecentConnectionsFilterAction = new RecentConnectionsFilterAction(RecentConnectionsFilterAction.ID, RecentConnectionsFilterAction.LABEL, serverTreeView.object, connectionManagementService.object);
|
||||
connectionTreeAction.run().then((value) => {
|
||||
serverTreeView.verify(x => x.showFilteredTree('recent'), TypeMoq.Times.once());
|
||||
}).then(() => done(), (err) => done(err));
|
||||
});
|
||||
|
||||
test('RecentConnectionsFilterAction - test if view is called refresh results if action is toggled', (done) => {
|
||||
let connectionManagementService = createConnectionManagementService(true);
|
||||
|
||||
let instantiationService = TypeMoq.Mock.ofType(InstantiationService, TypeMoq.MockBehavior.Loose);
|
||||
instantiationService.setup(x => x.createInstance(TypeMoq.It.isAny())).returns((input) => {
|
||||
return new TPromise((resolve) => resolve({}));
|
||||
});
|
||||
|
||||
let serverTreeView = TypeMoq.Mock.ofType(ServerTreeView, TypeMoq.MockBehavior.Strict, undefined, instantiationService.object, undefined, undefined, undefined);
|
||||
serverTreeView.setup(x => x.showFilteredTree(TypeMoq.It.isAnyString()));
|
||||
serverTreeView.setup(x => x.refreshTree());
|
||||
let connectionTreeAction: RecentConnectionsFilterAction = new RecentConnectionsFilterAction(RecentConnectionsFilterAction.ID, RecentConnectionsFilterAction.LABEL, serverTreeView.object, connectionManagementService.object);
|
||||
connectionTreeAction.isSet = true;
|
||||
connectionTreeAction.run().then((value) => {
|
||||
serverTreeView.verify(x => x.refreshTree(), TypeMoq.Times.once());
|
||||
}).then(() => done(), (err) => done(err));
|
||||
});
|
||||
|
||||
test('DeleteConnectionAction - test delete connection', (done) => {
|
||||
let connectionManagementService = createConnectionManagementService(true);
|
||||
|
||||
let connection: ConnectionProfile = new ConnectionProfile(undefined, {
|
||||
savePassword: false,
|
||||
groupFullName: 'testGroup',
|
||||
serverName: 'testServerName',
|
||||
databaseName: 'testDatabaseName',
|
||||
authenticationType: 'integrated',
|
||||
password: 'test',
|
||||
userName: 'testUsername',
|
||||
groupId: undefined,
|
||||
getOptionsKey: undefined,
|
||||
matches: undefined,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: 'testId'
|
||||
});
|
||||
let connectionAction: DeleteConnectionAction = new DeleteConnectionAction(DeleteConnectionAction.ID,
|
||||
DeleteConnectionAction.DELETE_CONNECTION_LABEL,
|
||||
connection,
|
||||
connectionManagementService.object);
|
||||
|
||||
connectionAction.run().then((value) => {
|
||||
connectionManagementService.verify(x => x.deleteConnection(TypeMoq.It.isAny()), TypeMoq.Times.atLeastOnce());
|
||||
}).then(() => done(), (err) => done(err));
|
||||
|
||||
});
|
||||
|
||||
test('DeleteConnectionAction - test delete connection group', (done) => {
|
||||
let isConnectedReturnValue: boolean = false;
|
||||
let connectionManagementService = createConnectionManagementService(isConnectedReturnValue);
|
||||
let conProfGroup = new ConnectionProfileGroup('testGroup', undefined, 'testGroup', undefined, undefined);
|
||||
let connectionAction: DeleteConnectionAction = new DeleteConnectionAction(DeleteConnectionAction.ID,
|
||||
DeleteConnectionAction.DELETE_CONNECTION_LABEL,
|
||||
conProfGroup,
|
||||
connectionManagementService.object);
|
||||
|
||||
connectionAction.run().then((value) => {
|
||||
connectionManagementService.verify(x => x.deleteConnectionGroup(TypeMoq.It.isAny()), TypeMoq.Times.atLeastOnce());
|
||||
}).then(() => done(), (err) => done(err));
|
||||
|
||||
});
|
||||
|
||||
test('DeleteConnectionAction - delete should not be called if connect is an unsaved connection', (done) => {
|
||||
let isConnectedReturnValue: boolean = false;
|
||||
let connectionManagementService = createConnectionManagementService(isConnectedReturnValue);
|
||||
|
||||
let connection: ConnectionProfile = new ConnectionProfile(undefined, {
|
||||
savePassword: false,
|
||||
groupFullName: 'testGroup',
|
||||
serverName: 'testServerName',
|
||||
databaseName: 'testDatabaseName',
|
||||
authenticationType: 'integrated',
|
||||
password: 'test',
|
||||
userName: 'testUsername',
|
||||
groupId: undefined,
|
||||
getOptionsKey: undefined,
|
||||
matches: undefined,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: 'testId'
|
||||
});
|
||||
connection.parent = new ConnectionProfileGroup(LocalizedConstants.unsavedGroupLabel, undefined, Constants.unsavedGroupId, undefined, undefined);
|
||||
let connectionAction: DeleteConnectionAction = new DeleteConnectionAction(DeleteConnectionAction.ID,
|
||||
DeleteConnectionAction.DELETE_CONNECTION_LABEL,
|
||||
connection,
|
||||
connectionManagementService.object);
|
||||
|
||||
assert.equal(connectionAction.enabled, false, 'delete action should be disabled.');
|
||||
done();
|
||||
});
|
||||
|
||||
test('RefreshConnectionAction - refresh should be called if connection status is connect', (done) => {
|
||||
let isConnectedReturnValue: boolean = true;
|
||||
let sqlProvider = {
|
||||
protocolVersion: '1',
|
||||
providerName: 'MSSQL',
|
||||
providerDisplayName: 'MSSQL',
|
||||
connectionProvider: { options: [] },
|
||||
adminServicesProvider: { databaseInfoOptions: [], databaseFileInfoOptions: [], fileGroupInfoOptions: [] },
|
||||
features: undefined
|
||||
};
|
||||
|
||||
var connection = new ConnectionProfile(sqlProvider, {
|
||||
savePassword: false,
|
||||
groupFullName: 'testGroup',
|
||||
serverName: 'testServerName',
|
||||
databaseName: 'testDatabaseName',
|
||||
authenticationType: 'inetgrated',
|
||||
password: 'test',
|
||||
userName: 'testUsername',
|
||||
groupId: undefined,
|
||||
getOptionsKey: undefined,
|
||||
matches: undefined,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: 'testID'
|
||||
});
|
||||
var conProfGroup = new ConnectionProfileGroup('testGroup', undefined, 'testGroup', undefined, undefined);
|
||||
conProfGroup.connections = [connection];
|
||||
var connectionManagementService = TypeMoq.Mock.ofType(TestConnectionManagementService, TypeMoq.MockBehavior.Strict);
|
||||
connectionManagementService.callBase = true;
|
||||
connectionManagementService.setup(x => x.getConnectionGroups()).returns(() => [conProfGroup]);
|
||||
connectionManagementService.setup(x => x.getActiveConnections()).returns(() => [connection]);
|
||||
connectionManagementService.setup(x => x.addSavedPassword(TypeMoq.It.isAny())).returns(() => new Promise<ConnectionProfile>((resolve) => {
|
||||
resolve(connection);
|
||||
}));
|
||||
connectionManagementService.setup(x => x.isConnected(undefined, TypeMoq.It.isAny())).returns(() => isConnectedReturnValue);
|
||||
|
||||
var objectExplorerSession = {
|
||||
success: true,
|
||||
sessionId: '1234',
|
||||
rootNode: {
|
||||
nodePath: 'testServerName\tables',
|
||||
nodeType: NodeType.Folder,
|
||||
label: 'Tables',
|
||||
isLeaf: false,
|
||||
metadata: null,
|
||||
nodeSubType: '',
|
||||
nodeStatus: '',
|
||||
errorMessage: ''
|
||||
},
|
||||
errorMessage: ''
|
||||
};
|
||||
|
||||
var tablesNode = new TreeNode(NodeType.Folder, 'Tables', false, 'testServerName\Db1\tables', '', '', null, null);
|
||||
tablesNode.connection = connection;
|
||||
tablesNode.session = objectExplorerSession;
|
||||
var table1Node = new TreeNode(NodeType.Table, 'dbo.Table1', false, 'testServerName\tables\dbo.Table1', '', '', tablesNode, null);
|
||||
var table2Node = new TreeNode(NodeType.Table, 'dbo.Table1', false, 'testServerName\tables\dbo.Table1', '', '', tablesNode, null);
|
||||
tablesNode.children = [table1Node, table2Node];
|
||||
let objectExplorerService = TypeMoq.Mock.ofType(ObjectExplorerService, TypeMoq.MockBehavior.Loose, connectionManagementService.object);
|
||||
objectExplorerService.callBase = true;
|
||||
objectExplorerService.setup(x => x.getObjectExplorerNode(TypeMoq.It.isAny())).returns(() => tablesNode);
|
||||
objectExplorerService.setup(x => x.refreshTreeNode(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => TPromise.as([table1Node, table2Node]));
|
||||
let builder: Builder = $().div();
|
||||
var dataSource = new ServerTreeDataSource(objectExplorerService.object, connectionManagementService.object, undefined);
|
||||
let tree = TypeMoq.Mock.ofType(Tree, TypeMoq.MockBehavior.Loose, builder.getHTMLElement(), { dataSource });
|
||||
tree.callBase = true;
|
||||
|
||||
tree.setup(x => x.refresh(TypeMoq.It.isAny())).returns(() => WinJS.TPromise.as(null));
|
||||
tree.setup(x => x.expand(TypeMoq.It.isAny())).returns(() => WinJS.TPromise.as(null));
|
||||
tree.setup(x => x.collapse(TypeMoq.It.isAny())).returns(() => WinJS.TPromise.as(null));
|
||||
let connectionAction: RefreshAction = new RefreshAction(RefreshAction.ID,
|
||||
RefreshAction.LABEL,
|
||||
tree.object,
|
||||
connection,
|
||||
connectionManagementService.object,
|
||||
objectExplorerService.object,
|
||||
undefined);
|
||||
|
||||
connectionAction.run().then((value) => {
|
||||
connectionManagementService.verify(x => x.isConnected(undefined, TypeMoq.It.isAny()), TypeMoq.Times.atLeastOnce());
|
||||
objectExplorerService.verify(x => x.getObjectExplorerNode(TypeMoq.It.isAny()), TypeMoq.Times.atLeastOnce());
|
||||
objectExplorerService.verify(x => x.refreshTreeNode(TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.atLeastOnce());
|
||||
tree.verify(x => x.refresh(TypeMoq.It.isAny()), TypeMoq.Times.atLeastOnce());
|
||||
tree.verify(x => x.expand(TypeMoq.It.isAny()), TypeMoq.Times.atLeastOnce());
|
||||
}).then(() => done(), (err) => done(err));
|
||||
});
|
||||
|
||||
test('RefreshConnectionAction - refresh should not be called if connection status is not connect', (done) => {
|
||||
let isConnectedReturnValue: boolean = false;
|
||||
let sqlProvider = {
|
||||
protocolVersion: '1',
|
||||
providerName: 'MSSQL',
|
||||
providerDisplayName: 'MSSQL',
|
||||
connectionProvider: { options: [] },
|
||||
adminServicesProvider: { databaseInfoOptions: [], databaseFileInfoOptions: [], fileGroupInfoOptions: [] },
|
||||
features: undefined
|
||||
};
|
||||
|
||||
var connection = new ConnectionProfile(sqlProvider, {
|
||||
savePassword: false,
|
||||
groupFullName: 'testGroup',
|
||||
serverName: 'testServerName',
|
||||
databaseName: 'testDatabaseName',
|
||||
authenticationType: 'inetgrated',
|
||||
password: 'test',
|
||||
userName: 'testUsername',
|
||||
groupId: undefined,
|
||||
getOptionsKey: undefined,
|
||||
matches: undefined,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: 'testID'
|
||||
});
|
||||
var conProfGroup = new ConnectionProfileGroup('testGroup', undefined, 'testGroup', undefined, undefined);
|
||||
conProfGroup.connections = [connection];
|
||||
var connectionManagementService = TypeMoq.Mock.ofType(TestConnectionManagementService, TypeMoq.MockBehavior.Strict);
|
||||
connectionManagementService.callBase = true;
|
||||
connectionManagementService.setup(x => x.getConnectionGroups()).returns(() => [conProfGroup]);
|
||||
connectionManagementService.setup(x => x.getActiveConnections()).returns(() => [connection]);
|
||||
connectionManagementService.setup(x => x.addSavedPassword(TypeMoq.It.isAny())).returns(() => new Promise<ConnectionProfile>((resolve) => {
|
||||
resolve(connection);
|
||||
}));
|
||||
connectionManagementService.setup(x => x.isConnected(undefined, TypeMoq.It.isAny())).returns(() => isConnectedReturnValue);
|
||||
|
||||
var objectExplorerSession = {
|
||||
success: true,
|
||||
sessionId: '1234',
|
||||
rootNode: {
|
||||
nodePath: 'testServerName\tables',
|
||||
nodeType: NodeType.Folder,
|
||||
label: 'Tables',
|
||||
isLeaf: false,
|
||||
metadata: null,
|
||||
nodeSubType: '',
|
||||
nodeStatus: '',
|
||||
errorMessage: ''
|
||||
},
|
||||
errorMessage: ''
|
||||
};
|
||||
|
||||
var tablesNode = new TreeNode(NodeType.Folder, 'Tables', false, 'testServerName\Db1\tables', '', '', null, null);
|
||||
tablesNode.connection = connection;
|
||||
tablesNode.session = objectExplorerSession;
|
||||
var table1Node = new TreeNode(NodeType.Table, 'dbo.Table1', false, 'testServerName\tables\dbo.Table1', '', '', tablesNode, null);
|
||||
var table2Node = new TreeNode(NodeType.Table, 'dbo.Table1', false, 'testServerName\tables\dbo.Table1', '', '', tablesNode, null);
|
||||
tablesNode.children = [table1Node, table2Node];
|
||||
let objectExplorerService = TypeMoq.Mock.ofType(ObjectExplorerService, TypeMoq.MockBehavior.Loose, connectionManagementService.object);
|
||||
objectExplorerService.callBase = true;
|
||||
objectExplorerService.setup(x => x.getObjectExplorerNode(TypeMoq.It.isAny())).returns(() => tablesNode);
|
||||
objectExplorerService.setup(x => x.refreshTreeNode(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => TPromise.as([table1Node, table2Node]));
|
||||
let builder: Builder = $().div();
|
||||
var dataSource = new ServerTreeDataSource(objectExplorerService.object, connectionManagementService.object, undefined);
|
||||
let tree = TypeMoq.Mock.ofType(Tree, TypeMoq.MockBehavior.Loose, builder.getHTMLElement(), { dataSource });
|
||||
tree.callBase = true;
|
||||
|
||||
tree.setup(x => x.refresh(TypeMoq.It.isAny())).returns(() => WinJS.TPromise.as(null));
|
||||
tree.setup(x => x.expand(TypeMoq.It.isAny())).returns(() => WinJS.TPromise.as(null));
|
||||
let connectionAction: RefreshAction = new RefreshAction(RefreshAction.ID,
|
||||
RefreshAction.LABEL,
|
||||
tree.object,
|
||||
connection,
|
||||
connectionManagementService.object,
|
||||
objectExplorerService.object,
|
||||
undefined);
|
||||
|
||||
connectionAction.run().then((value) => {
|
||||
connectionManagementService.verify(x => x.isConnected(undefined, TypeMoq.It.isAny()), TypeMoq.Times.atLeastOnce());
|
||||
objectExplorerService.verify(x => x.getObjectExplorerNode(TypeMoq.It.isAny()), TypeMoq.Times.exactly(0));
|
||||
objectExplorerService.verify(x => x.refreshTreeNode(TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.exactly(0));
|
||||
tree.verify(x => x.refresh(TypeMoq.It.isAny()), TypeMoq.Times.exactly(0));
|
||||
tree.verify(x => x.expand(TypeMoq.It.isAny()), TypeMoq.Times.exactly(0));
|
||||
}).then(() => done(), (err) => done(err));
|
||||
});
|
||||
|
||||
});
|
||||
450
src/sqltest/parts/connection/objectExplorerService.test.ts
Normal file
450
src/sqltest/parts/connection/objectExplorerService.test.ts
Normal file
@@ -0,0 +1,450 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
import { ObjectExplorerProviderTestService } from 'sqltest/stubs/objectExplorerProviderTestService';
|
||||
import { TestConnectionManagementService } from 'sqltest/stubs/connectionManagementService.test';
|
||||
import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
|
||||
import { ConnectionProfileGroup } from 'sql/parts/connection/common/connectionProfileGroup';
|
||||
import { ObjectExplorerService } from 'sql/parts/registeredServer/common/objectExplorerService';
|
||||
import { NodeType } from 'sql/parts/registeredServer/common/nodeType';
|
||||
import { TreeNode } from 'sql/parts/registeredServer/common/treeNode';
|
||||
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import * as data from 'data';
|
||||
import * as TypeMoq from 'typemoq';
|
||||
import * as assert from 'assert';
|
||||
|
||||
suite('SQL Object Explorer Service tests', () => {
|
||||
var sqlOEProvider: TypeMoq.Mock<ObjectExplorerProviderTestService>;
|
||||
let connectionManagementService: TypeMoq.Mock<TestConnectionManagementService>;
|
||||
let connection: ConnectionProfile;
|
||||
let connectionToFail: ConnectionProfile;
|
||||
let conProfGroup: ConnectionProfileGroup;
|
||||
let objectExplorerService: ObjectExplorerService;
|
||||
let objectExplorerSession: data.ObjectExplorerSession;
|
||||
let objectExplorerFailedSession: data.ObjectExplorerSession;
|
||||
let objectExplorerCloseSessionResponse: data.ObjectExplorerCloseSessionResponse;
|
||||
let objectExplorerExpandInfo: data.ObjectExplorerExpandInfo;
|
||||
let objectExplorerExpandInfoRefresh: data.ObjectExplorerExpandInfo;
|
||||
let sessionId = '1234';
|
||||
let failedSessionId = '12345';
|
||||
let numberOfFailedSession: number = 0;
|
||||
|
||||
setup(() => {
|
||||
|
||||
let NodeInfoTable1 = {
|
||||
nodePath: 'testServerName\tables\dbo.Table1',
|
||||
nodeType: NodeType.Table,
|
||||
label: 'dbo.Table1',
|
||||
isLeaf: false,
|
||||
metadata: null,
|
||||
nodeSubType: '',
|
||||
nodeStatus: '',
|
||||
errorMessage: ''
|
||||
};
|
||||
let NodeInfoTable2 = {
|
||||
nodePath: 'testServerName\tables\dbo.Table2',
|
||||
nodeType: NodeType.Table,
|
||||
label: 'dbo.Table2',
|
||||
isLeaf: false,
|
||||
metadata: null,
|
||||
nodeSubType: '',
|
||||
nodeStatus: '',
|
||||
errorMessage: ''
|
||||
};
|
||||
|
||||
let NodeInfoTable3 = {
|
||||
nodePath: 'testServerName\tables\dbo.Table3',
|
||||
nodeType: NodeType.Table,
|
||||
label: 'dbo.Table3',
|
||||
isLeaf: false,
|
||||
metadata: null,
|
||||
nodeSubType: '',
|
||||
nodeStatus: '',
|
||||
errorMessage: ''
|
||||
};
|
||||
|
||||
objectExplorerSession = {
|
||||
success: true,
|
||||
sessionId: sessionId,
|
||||
rootNode: {
|
||||
nodePath: 'testServerName\tables',
|
||||
nodeType: NodeType.Folder,
|
||||
label: 'Tables',
|
||||
isLeaf: false,
|
||||
metadata: null,
|
||||
nodeSubType: '',
|
||||
nodeStatus: '',
|
||||
errorMessage: ''
|
||||
},
|
||||
errorMessage: ''
|
||||
};
|
||||
|
||||
objectExplorerFailedSession = {
|
||||
success: false,
|
||||
sessionId: failedSessionId,
|
||||
rootNode: undefined,
|
||||
errorMessage: 'Connection Failed'
|
||||
};
|
||||
|
||||
objectExplorerCloseSessionResponse = {
|
||||
success: true,
|
||||
sessionId: sessionId,
|
||||
};
|
||||
|
||||
objectExplorerExpandInfo = {
|
||||
sessionId: sessionId,
|
||||
nodes: [NodeInfoTable1, NodeInfoTable2],
|
||||
errorMessage: '',
|
||||
nodePath: objectExplorerSession.rootNode.nodePath
|
||||
};
|
||||
|
||||
objectExplorerExpandInfoRefresh = {
|
||||
sessionId: sessionId,
|
||||
nodes: [NodeInfoTable1, NodeInfoTable3],
|
||||
errorMessage: '',
|
||||
nodePath: objectExplorerSession.rootNode.nodePath
|
||||
};
|
||||
let response: data.ObjectExplorerSessionResponse = {
|
||||
sessionId: objectExplorerSession.sessionId
|
||||
};
|
||||
|
||||
let failedResponse: data.ObjectExplorerSessionResponse = {
|
||||
sessionId: failedSessionId
|
||||
};
|
||||
|
||||
sqlOEProvider = TypeMoq.Mock.ofType(ObjectExplorerProviderTestService, TypeMoq.MockBehavior.Loose);
|
||||
sqlOEProvider.callBase = true;
|
||||
|
||||
|
||||
let sqlProvider = {
|
||||
protocolVersion: '1',
|
||||
providerName: 'MSSQL',
|
||||
providerDisplayName: 'MSSQL',
|
||||
connectionProvider: {
|
||||
options: [
|
||||
{
|
||||
name: 'serverName',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 0,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'databaseName',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 1,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'userName',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 3,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'authenticationType',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 2,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'password',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 4,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'encrypt',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: false,
|
||||
isRequired: false,
|
||||
specialValueType: undefined,
|
||||
valueType: 0
|
||||
}]
|
||||
},
|
||||
adminServicesProvider: { databaseInfoOptions: [], databaseFileInfoOptions: [], fileGroupInfoOptions: [] },
|
||||
features: undefined
|
||||
};
|
||||
|
||||
connection = new ConnectionProfile(sqlProvider, {
|
||||
savePassword: false,
|
||||
groupFullName: 'testGroup',
|
||||
serverName: 'testServerName',
|
||||
databaseName: 'testDatabaseName',
|
||||
authenticationType: 'inetgrated',
|
||||
password: 'test',
|
||||
userName: 'testUsername',
|
||||
groupId: undefined,
|
||||
getOptionsKey: undefined,
|
||||
matches: undefined,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: 'testID'
|
||||
});
|
||||
conProfGroup = new ConnectionProfileGroup('testGroup', undefined, 'testGroup', undefined, undefined);
|
||||
|
||||
connectionToFail = new ConnectionProfile(sqlProvider, {
|
||||
savePassword: false,
|
||||
groupFullName: 'testGroup',
|
||||
serverName: 'testServerName2',
|
||||
databaseName: 'testDatabaseName2',
|
||||
authenticationType: 'inetgrated',
|
||||
password: 'test',
|
||||
userName: 'testUsername',
|
||||
groupId: undefined,
|
||||
getOptionsKey: undefined,
|
||||
matches: undefined,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: 'testID2'
|
||||
});
|
||||
conProfGroup = new ConnectionProfileGroup('testGroup', undefined, 'testGroup', undefined, undefined);
|
||||
conProfGroup.connections = [connection];
|
||||
connectionManagementService = TypeMoq.Mock.ofType(TestConnectionManagementService, TypeMoq.MockBehavior.Strict);
|
||||
connectionManagementService.setup(x => x.getConnectionGroups()).returns(() => [conProfGroup]);
|
||||
connectionManagementService.setup(x => x.getActiveConnections()).returns(() => [connection]);
|
||||
connectionManagementService.setup(x => x.addSavedPassword(TypeMoq.It.isAny())).returns(() => new Promise<ConnectionProfile>((resolve) => {
|
||||
resolve(connection);
|
||||
}));
|
||||
|
||||
connectionManagementService.setup(x => x.getCapabilities('MSSQL')).returns(() => undefined);
|
||||
|
||||
objectExplorerService = new ObjectExplorerService(connectionManagementService.object, undefined);
|
||||
objectExplorerService.registerProvider('MSSQL', sqlOEProvider.object);
|
||||
sqlOEProvider.setup(x => x.createNewSession(TypeMoq.It.is<data.ConnectionInfo>(x => x.options['serverName'] === connection.serverName))).returns(() => new Promise<any>((resolve) => {
|
||||
resolve(response);
|
||||
}));
|
||||
sqlOEProvider.setup(x => x.createNewSession(TypeMoq.It.is<data.ConnectionInfo>(x => x.options['serverName'] === connectionToFail.serverName))).returns(() => new Promise<any>((resolve) => {
|
||||
resolve(failedResponse);
|
||||
}));
|
||||
sqlOEProvider.setup(x => x.expandNode(TypeMoq.It.isAny())).callback(() => {
|
||||
objectExplorerService.onNodeExpanded(1, objectExplorerExpandInfo);
|
||||
}).returns(() => TPromise.as(true));
|
||||
sqlOEProvider.setup(x => x.refreshNode(TypeMoq.It.isAny())).callback(() => {
|
||||
objectExplorerService.onNodeExpanded(1, objectExplorerExpandInfoRefresh);
|
||||
}).returns(() => TPromise.as(true));
|
||||
sqlOEProvider.setup(x => x.closeSession(TypeMoq.It.isAny())).returns(() => TPromise.as(objectExplorerCloseSessionResponse));
|
||||
|
||||
objectExplorerService.onUpdateObjectExplorerNodes(args => {
|
||||
if (args && args.errorMessage !== undefined) {
|
||||
numberOfFailedSession++;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('create new session should create session successfully', (done) => {
|
||||
objectExplorerService.createNewSession('MSSQL', connection).then(session => {
|
||||
assert.equal(session !== null || session !== undefined, true);
|
||||
assert.equal(session.sessionId, '1234');
|
||||
objectExplorerService.onSessionCreated(1, objectExplorerSession);
|
||||
let node = objectExplorerService.getObjectExplorerNode(connection);
|
||||
assert.notEqual(node, undefined);
|
||||
assert.equal(node.session.success, true);
|
||||
done();
|
||||
}, err => {
|
||||
// Must call done here so test indicates it's finished if errors occur
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
test('create new session should raise failed event for failed session', (done) => {
|
||||
objectExplorerService.createNewSession('MSSQL', connectionToFail).then(session => {
|
||||
assert.equal(session !== null || session !== undefined, true);
|
||||
assert.equal(session.sessionId, failedSessionId);
|
||||
let currentNumberOfFailedSession = numberOfFailedSession;
|
||||
objectExplorerService.onSessionCreated(1, objectExplorerFailedSession);
|
||||
let node = objectExplorerService.getObjectExplorerNode(connection);
|
||||
assert.equal(node, undefined);
|
||||
assert.equal(currentNumberOfFailedSession + 1, numberOfFailedSession);
|
||||
done();
|
||||
}, err => {
|
||||
// Must call done here so test indicates it's finished if errors occur
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
test('close session should close session successfully', (done) => {
|
||||
objectExplorerService.closeSession('MSSQL', objectExplorerSession).then(session => {
|
||||
assert.equal(session !== null || session !== undefined, true);
|
||||
assert.equal(session.success, true);
|
||||
assert.equal(session.sessionId, '1234');
|
||||
done();
|
||||
}, err => {
|
||||
// Must call done here so test indicates it's finished if errors occur
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
test('expand node should expand node correctly', (done) => {
|
||||
objectExplorerService.createNewSession('MSSQL', connection).then(result => {
|
||||
objectExplorerService.onSessionCreated(1, objectExplorerSession);
|
||||
objectExplorerService.expandNode('MSSQL', objectExplorerSession, 'testServerName\tables').then(expandInfo => {
|
||||
assert.equal(expandInfo !== null || expandInfo !== undefined, true);
|
||||
assert.equal(expandInfo.sessionId, '1234');
|
||||
assert.equal(expandInfo.nodes.length, 2);
|
||||
var children = expandInfo.nodes;
|
||||
assert.equal(children[0].label, 'dbo.Table1');
|
||||
assert.equal(children[1].label, 'dbo.Table2');
|
||||
done();
|
||||
}, err => {
|
||||
// Must call done here so test indicates it's finished if errors occur
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('refresh node should refresh node correctly', (done) => {
|
||||
objectExplorerService.createNewSession('MSSQL', connection).then(result => {
|
||||
objectExplorerService.onSessionCreated(1, objectExplorerSession);
|
||||
objectExplorerService.refreshNode('MSSQL', objectExplorerSession, 'testServerName\tables').then(expandInfo => {
|
||||
assert.equal(expandInfo !== null || expandInfo !== undefined, true);
|
||||
assert.equal(expandInfo.sessionId, '1234');
|
||||
assert.equal(expandInfo.nodes.length, 2);
|
||||
var children = expandInfo.nodes;
|
||||
assert.equal(children[0].label, 'dbo.Table1');
|
||||
assert.equal(children[1].label, 'dbo.Table3');
|
||||
done();
|
||||
}, err => {
|
||||
// Must call done here so test indicates it's finished if errors occur
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('expand tree node should children correctly', (done) => {
|
||||
var tablesNode = new TreeNode(NodeType.Folder, 'Tables', false, 'testServerName\tables', '', '', null, null);
|
||||
tablesNode.connection = connection;
|
||||
objectExplorerService.createNewSession('MSSQL', connection).then(result => {
|
||||
objectExplorerService.onSessionCreated(1, objectExplorerSession);
|
||||
objectExplorerService.expandTreeNode(objectExplorerSession, tablesNode).then(children => {
|
||||
assert.equal(children !== null || children !== undefined, true);
|
||||
assert.equal(children[0].label, 'dbo.Table1');
|
||||
assert.equal(children[0].parent, tablesNode);
|
||||
assert.equal(children[0].nodePath, 'testServerName\tables\dbo.Table1');
|
||||
assert.equal(children[1].label, 'dbo.Table2');
|
||||
assert.equal(children[1].parent, tablesNode);
|
||||
assert.equal(children[1].nodePath, 'testServerName\tables\dbo.Table2');
|
||||
done();
|
||||
}, err => {
|
||||
// Must call done here so test indicates it's finished if errors occur
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('refresh tree node should children correctly', (done) => {
|
||||
var tablesNode = new TreeNode(NodeType.Folder, 'Tables', false, 'testServerName\tables', '', '', null, null);
|
||||
tablesNode.connection = connection;
|
||||
objectExplorerService.createNewSession('MSSQL', connection).then(result => {
|
||||
objectExplorerService.onSessionCreated(1, objectExplorerSession);
|
||||
objectExplorerService.refreshTreeNode(objectExplorerSession, tablesNode).then(children => {
|
||||
assert.equal(children !== null || children !== undefined, true);
|
||||
assert.equal(children[0].label, 'dbo.Table1');
|
||||
assert.equal(children[0].parent, tablesNode);
|
||||
assert.equal(children[0].nodePath, 'testServerName\tables\dbo.Table1');
|
||||
assert.equal(children[1].label, 'dbo.Table3');
|
||||
assert.equal(children[1].parent, tablesNode);
|
||||
assert.equal(children[1].nodePath, 'testServerName\tables\dbo.Table3');
|
||||
done();
|
||||
}, err => {
|
||||
// Must call done here so test indicates it's finished if errors occur
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('update object explorer nodes should get active connection, create session, add to the active OE nodes successfully', (done) => {
|
||||
objectExplorerService.createNewSession('MSSQL', connection).then(result => {
|
||||
objectExplorerService.onSessionCreated(1, objectExplorerSession);
|
||||
objectExplorerService.updateObjectExplorerNodes(connection).then(() => {
|
||||
var treeNode = objectExplorerService.getObjectExplorerNode(connection);
|
||||
assert.equal(treeNode !== null || treeNode !== undefined, true);
|
||||
assert.equal(treeNode.getSession(), objectExplorerSession);
|
||||
assert.equal(treeNode.getConnectionProfile(), connection);
|
||||
assert.equal(treeNode.label, 'Tables');
|
||||
assert.equal(treeNode.nodePath, 'testServerName\tables');
|
||||
done();
|
||||
}, err => {
|
||||
// Must call done here so test indicates it's finished if errors occur
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('delete object explorerNode nodes should delete session, delete the root node to the active OE node', (done) => {
|
||||
objectExplorerService.createNewSession('MSSQL', connection).then(result => {
|
||||
objectExplorerService.onSessionCreated(1, objectExplorerSession);
|
||||
objectExplorerService.updateObjectExplorerNodes(connection).then(() => {
|
||||
var treeNode = objectExplorerService.getObjectExplorerNode(connection);
|
||||
assert.equal(treeNode !== null && treeNode !== undefined, true);
|
||||
objectExplorerService.deleteObjectExplorerNode(connection);
|
||||
treeNode = objectExplorerService.getObjectExplorerNode(connection);
|
||||
assert.equal(treeNode === null || treeNode === undefined, true);
|
||||
done();
|
||||
}, err => {
|
||||
// Must call done here so test indicates it's finished if errors occur
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('children tree nodes should return correct object explorer session, connection profile and database name', () => {
|
||||
var databaseMetaData = {
|
||||
metadataType: 0,
|
||||
metadataTypeName: 'Database',
|
||||
urn: '//server/db1/',
|
||||
name: 'Db1',
|
||||
schema: null
|
||||
};
|
||||
var databaseNode = new TreeNode(NodeType.Database, 'Db1', false, 'testServerName\Db1', '', '', null, databaseMetaData);
|
||||
databaseNode.connection = connection;
|
||||
databaseNode.session = objectExplorerSession;
|
||||
var tablesNode = new TreeNode(NodeType.Folder, 'Tables', false, 'testServerName\Db1\tables', '', '', databaseNode, null);
|
||||
databaseNode.children = [tablesNode];
|
||||
var table1Node = new TreeNode(NodeType.Table, 'dbo.Table1', false, 'testServerName\Db1\tables\dbo.Table1', '', '', tablesNode, null);
|
||||
var table2Node = new TreeNode(NodeType.Table, 'dbo.Table2', false, 'testServerName\Db1\tables\dbo.Table2', '', '', tablesNode, null);
|
||||
tablesNode.children = [table1Node, table2Node];
|
||||
assert.equal(table1Node.getSession(), objectExplorerSession);
|
||||
assert.equal(table1Node.getConnectionProfile(), connection);
|
||||
assert.equal(table1Node.getDatabaseName(), 'Db1');
|
||||
});
|
||||
});
|
||||
248
src/sqltest/parts/connection/providerConnectionInfo.test.ts
Normal file
248
src/sqltest/parts/connection/providerConnectionInfo.test.ts
Normal file
@@ -0,0 +1,248 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
|
||||
import { ProviderConnectionInfo } from 'sql/parts/connection/common/providerConnectionInfo';
|
||||
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
||||
import data = require('data');
|
||||
import * as assert from 'assert';
|
||||
|
||||
suite('SQL ProviderConnectionInfo tests', () => {
|
||||
let msSQLCapabilities: data.DataProtocolServerCapabilities;
|
||||
|
||||
let connectionProfile: IConnectionProfile = {
|
||||
serverName: 'new server',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g2/g2-2',
|
||||
groupId: undefined,
|
||||
getOptionsKey: undefined,
|
||||
matches: undefined,
|
||||
providerName: 'MSSQL',
|
||||
options: undefined,
|
||||
saveProfile: true,
|
||||
id: undefined
|
||||
};
|
||||
|
||||
setup(() => {
|
||||
let capabilities: data.DataProtocolServerCapabilities[] = [];
|
||||
let connectionProvider: data.ConnectionProviderOptions = {
|
||||
options: [
|
||||
{
|
||||
name: 'serverName',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 0,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'databaseName',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 1,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'userName',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 3,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'authenticationType',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 2,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'password',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 4,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'encrypt',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: false,
|
||||
isRequired: false,
|
||||
specialValueType: undefined,
|
||||
valueType: 0
|
||||
}
|
||||
]
|
||||
};
|
||||
msSQLCapabilities = {
|
||||
protocolVersion: '1',
|
||||
providerName: 'MSSQL',
|
||||
providerDisplayName: 'MSSQL',
|
||||
connectionProvider: connectionProvider,
|
||||
adminServicesProvider: undefined,
|
||||
features: undefined
|
||||
};
|
||||
capabilities.push(msSQLCapabilities);
|
||||
});
|
||||
|
||||
test('constructor should accept undefined parameters', () => {
|
||||
let conn = new ProviderConnectionInfo(undefined, undefined);
|
||||
assert.equal(conn.serverName, undefined);
|
||||
});
|
||||
|
||||
test('set properties should set the values correctly', () => {
|
||||
let conn = new ProviderConnectionInfo(msSQLCapabilities, undefined);
|
||||
assert.equal(conn.serverName, undefined);
|
||||
conn.serverName = connectionProfile.serverName;
|
||||
conn.databaseName = connectionProfile.databaseName;
|
||||
conn.authenticationType = connectionProfile.authenticationType;
|
||||
conn.password = connectionProfile.password;
|
||||
conn.userName = connectionProfile.userName;
|
||||
assert.equal(conn.serverName, connectionProfile.serverName);
|
||||
assert.equal(conn.databaseName, connectionProfile.databaseName);
|
||||
assert.equal(conn.authenticationType, connectionProfile.authenticationType);
|
||||
assert.equal(conn.password, connectionProfile.password);
|
||||
assert.equal(conn.userName, connectionProfile.userName);
|
||||
});
|
||||
|
||||
test('set properties should store the values in the options', () => {
|
||||
let conn = new ProviderConnectionInfo(msSQLCapabilities, undefined);
|
||||
assert.equal(conn.serverName, undefined);
|
||||
conn.serverName = connectionProfile.serverName;
|
||||
conn.databaseName = connectionProfile.databaseName;
|
||||
conn.authenticationType = connectionProfile.authenticationType;
|
||||
conn.password = connectionProfile.password;
|
||||
conn.userName = connectionProfile.userName;
|
||||
assert.equal(conn.getOptionValue('serverName'), connectionProfile.serverName);
|
||||
assert.equal(conn.getOptionValue('databaseName'), connectionProfile.databaseName);
|
||||
assert.equal(conn.getOptionValue('authenticationType'), connectionProfile.authenticationType);
|
||||
assert.equal(conn.getOptionValue('password'), connectionProfile.password);
|
||||
assert.equal(conn.getOptionValue('userName'), connectionProfile.userName);
|
||||
});
|
||||
|
||||
test('constructor should initialize the options given a valid model', () => {
|
||||
let conn = new ProviderConnectionInfo(msSQLCapabilities, connectionProfile);
|
||||
|
||||
assert.equal(conn.serverName, connectionProfile.serverName);
|
||||
assert.equal(conn.databaseName, connectionProfile.databaseName);
|
||||
assert.equal(conn.authenticationType, connectionProfile.authenticationType);
|
||||
assert.equal(conn.password, connectionProfile.password);
|
||||
assert.equal(conn.userName, connectionProfile.userName);
|
||||
});
|
||||
|
||||
test('clone should create a new instance that equals the old one', () => {
|
||||
let conn = new ProviderConnectionInfo(msSQLCapabilities, connectionProfile);
|
||||
|
||||
let conn2 = conn.clone();
|
||||
assert.equal(conn.serverName, conn2.serverName);
|
||||
assert.equal(conn.databaseName, conn2.databaseName);
|
||||
assert.equal(conn.authenticationType, conn2.authenticationType);
|
||||
assert.equal(conn.password, conn2.password);
|
||||
assert.equal(conn.userName, conn2.userName);
|
||||
});
|
||||
|
||||
test('Changing the cloned object should not change the original one', () => {
|
||||
let conn = new ProviderConnectionInfo(msSQLCapabilities, connectionProfile);
|
||||
|
||||
let conn2 = conn.clone();
|
||||
conn2.serverName = conn.serverName + '1';
|
||||
assert.notEqual(conn.serverName, conn2.serverName);
|
||||
});
|
||||
|
||||
test('constructor should initialize the options given a valid model with options', () => {
|
||||
let options = {};
|
||||
options['encrypt'] = 'test value';
|
||||
let conn2 = Object.assign({}, connectionProfile, { options: options });
|
||||
let conn = new ProviderConnectionInfo(msSQLCapabilities, conn2);
|
||||
|
||||
assert.equal(conn.serverName, conn2.serverName);
|
||||
assert.equal(conn.databaseName, conn2.databaseName);
|
||||
assert.equal(conn.authenticationType, conn2.authenticationType);
|
||||
assert.equal(conn.password, conn2.password);
|
||||
assert.equal(conn.userName, conn2.userName);
|
||||
assert.equal(conn.options['encrypt'], 'test value');
|
||||
});
|
||||
|
||||
test('getOptionsKey should create a valid unique id', () => {
|
||||
let conn = new ProviderConnectionInfo(msSQLCapabilities, connectionProfile);
|
||||
let expectedId = 'providerName:MSSQL|authenticationType:|databaseName:database|serverName:new server|userName:user';
|
||||
let id = conn.getOptionsKey();
|
||||
assert.equal(id, expectedId);
|
||||
});
|
||||
|
||||
test('getOptionsKey should create different id for different server names', () => {
|
||||
let conn = new ProviderConnectionInfo(msSQLCapabilities, connectionProfile);
|
||||
let conn2 = new ProviderConnectionInfo(msSQLCapabilities, Object.assign({}, connectionProfile, { serverName: connectionProfile.serverName + '1' }));
|
||||
|
||||
assert.notEqual(conn.getOptionsKey(), conn2.getOptionsKey());
|
||||
});
|
||||
|
||||
test('titleParts should return server, database and auth type as first items', () => {
|
||||
let conn = new ProviderConnectionInfo(msSQLCapabilities, connectionProfile);
|
||||
let titleParts = conn.titleParts;
|
||||
assert.equal(titleParts.length, 4);
|
||||
assert.equal(titleParts[0], connectionProfile.serverName);
|
||||
assert.equal(titleParts[1], connectionProfile.databaseName);
|
||||
assert.equal(titleParts[2], connectionProfile.authenticationType);
|
||||
assert.equal(titleParts[3], connectionProfile.userName);
|
||||
});
|
||||
|
||||
test('getProviderFromOptionsKey should return the provider name from the options key successfully', () => {
|
||||
let optionsKey = 'providerName:MSSQL|authenticationType:|databaseName:database|serverName:new server|userName:user';
|
||||
let expectedProviderId: string = 'MSSQL';
|
||||
let actual = ProviderConnectionInfo.getProviderFromOptionsKey(optionsKey);
|
||||
|
||||
assert.equal(expectedProviderId, actual);
|
||||
});
|
||||
|
||||
test('getProviderFromOptionsKey should return empty string give null', () => {
|
||||
let optionsKey = undefined;
|
||||
let expectedProviderId: string = '';
|
||||
let actual = ProviderConnectionInfo.getProviderFromOptionsKey(optionsKey);
|
||||
|
||||
assert.equal(expectedProviderId, actual);
|
||||
});
|
||||
|
||||
test('getProviderFromOptionsKey should return empty string give key without provider name', () => {
|
||||
let optionsKey = 'providerName2:MSSQL|authenticationType:|databaseName:database|serverName:new server|userName:user';
|
||||
let expectedProviderId: string = '';
|
||||
let actual = ProviderConnectionInfo.getProviderFromOptionsKey(optionsKey);
|
||||
|
||||
assert.equal(expectedProviderId, actual);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,59 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ObjectMetadataWrapper } from 'sql/parts/dashboard/widgets/explorer/explorerWidget.component';
|
||||
import { MetadataType } from 'sql/parts/connection/common/connectionManagement';
|
||||
|
||||
import * as assert from 'assert';
|
||||
|
||||
suite('Explorer Widget Tests', () => {
|
||||
test('Sorting dashboard search objects works correctly', () => {
|
||||
let testMetadata = ObjectMetadataWrapper.createFromObjectMetadata(
|
||||
[
|
||||
{
|
||||
metadataType: MetadataType.View,
|
||||
metadataTypeName: undefined,
|
||||
urn: undefined,
|
||||
name: 'testView',
|
||||
schema: undefined
|
||||
},
|
||||
{
|
||||
metadataType: MetadataType.Table,
|
||||
metadataTypeName: undefined,
|
||||
urn: undefined,
|
||||
name: 'testTable',
|
||||
schema: undefined
|
||||
},
|
||||
{
|
||||
metadataType: MetadataType.SProc,
|
||||
metadataTypeName: undefined,
|
||||
urn: undefined,
|
||||
name: 'testSProc',
|
||||
schema: undefined
|
||||
},
|
||||
{
|
||||
metadataType: MetadataType.Function,
|
||||
metadataTypeName: undefined,
|
||||
urn: undefined,
|
||||
name: 'testFunction',
|
||||
schema: undefined
|
||||
},
|
||||
{
|
||||
metadataType: MetadataType.View,
|
||||
metadataTypeName: undefined,
|
||||
urn: undefined,
|
||||
name: 'firstView',
|
||||
schema: undefined
|
||||
}
|
||||
]);
|
||||
|
||||
// If I sort the object metadata wrapper list using ExplorerWidget's sort function
|
||||
let sortedMetadata = testMetadata.slice().sort(ObjectMetadataWrapper.sort);
|
||||
|
||||
// Then the resulting list is sorted by type, with Table > View > Stored Procedures > Function, then by name
|
||||
let expectedList = [testMetadata[1], testMetadata[4], testMetadata[0], testMetadata[2], testMetadata[3]];
|
||||
expectedList.forEach((expectedWrapper, index) => assert.equal(sortedMetadata[index], expectedWrapper));
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,108 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { ChangeDetectorRef } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
// of is not on Observable by default, need to import it
|
||||
import 'rxjs/add/observable/of';
|
||||
|
||||
import { WidgetConfig } from 'sql/parts/dashboard/common/dashboardWidget';
|
||||
import { DashboardServiceInterface, SingleAdminService, SingleConnectionManagementService } from 'sql/parts/dashboard/services/dashboardServiceInterface.service';
|
||||
import { PropertiesWidgetComponent } from 'sql/parts/dashboard/widgets/properties/propertiesWidget.component';
|
||||
import { ConnectionManagementInfo } from 'sql/parts/connection/common/connectionManagementInfo';
|
||||
|
||||
import * as TypeMoq from 'typemoq';
|
||||
import * as assert from 'assert';
|
||||
|
||||
class TestChangeDetectorRef extends ChangeDetectorRef {
|
||||
reattach(): void {
|
||||
return;
|
||||
}
|
||||
checkNoChanges(): void {
|
||||
return;
|
||||
}
|
||||
detectChanges(): void {
|
||||
return;
|
||||
}
|
||||
detach(): void {
|
||||
return;
|
||||
}
|
||||
markForCheck(): void {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
suite('Dashboard Properties Widget Tests', () => {
|
||||
test('Parses good config', (done) => {
|
||||
let propertiesConfig = {
|
||||
properties: [
|
||||
{
|
||||
|
||||
displayName: 'Test',
|
||||
value: 'testProperty'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
let serverInfo = {
|
||||
isCloud: false,
|
||||
testProperty: 'Test Property',
|
||||
serverMajorVersion: undefined,
|
||||
serverMinorVersion: undefined,
|
||||
serverReleaseVersion: undefined,
|
||||
engineEditionId: undefined,
|
||||
serverVersion: undefined,
|
||||
serverLevel: undefined,
|
||||
serverEdition: undefined,
|
||||
azureVersion: undefined,
|
||||
osVersion: undefined,
|
||||
};
|
||||
|
||||
let databaseInfo = {
|
||||
options: {
|
||||
testProperty: 'Test Property'
|
||||
}
|
||||
};
|
||||
|
||||
let widgetConfig: WidgetConfig = {
|
||||
widget: {
|
||||
'properties-widget': propertiesConfig
|
||||
},
|
||||
context: 'server',
|
||||
provider: 'MSSQL',
|
||||
edition: 0
|
||||
};
|
||||
|
||||
let dashboardService = TypeMoq.Mock.ofType(DashboardServiceInterface, TypeMoq.MockBehavior.Loose, [{}]);
|
||||
|
||||
let singleAdminService = TypeMoq.Mock.ofType(SingleAdminService);
|
||||
singleAdminService.setup(x => x.databaseInfo).returns(() => Observable.of(databaseInfo));
|
||||
|
||||
dashboardService.setup(x => x.adminService).returns(() => singleAdminService.object);
|
||||
|
||||
let connectionManagementinfo = TypeMoq.Mock.ofType(ConnectionManagementInfo);
|
||||
connectionManagementinfo.object.serverInfo = serverInfo;
|
||||
|
||||
let singleConnectionService = TypeMoq.Mock.ofType(SingleConnectionManagementService);
|
||||
singleConnectionService.setup(x => x.connectionInfo).returns(() => connectionManagementinfo.object);
|
||||
|
||||
dashboardService.setup(x => x.connectionManagementService).returns(() => singleConnectionService.object);
|
||||
|
||||
let consoleError = (message?: any, ...optionalParams: any[]): void => {
|
||||
assert.fail('Called console Error unexpectedly');
|
||||
};
|
||||
|
||||
let testComponent = new PropertiesWidgetComponent(dashboardService.object, new TestChangeDetectorRef(), undefined, widgetConfig, consoleError);
|
||||
|
||||
// because config parsing is done async we need to put our asserts on the thread stack
|
||||
setTimeout(() => {
|
||||
// because properties is private we need to do some work arounds to access it.
|
||||
assert.equal((<any>testComponent).properties.length, 1);
|
||||
assert.equal((<any>testComponent).properties[0].displayName, 'Test');
|
||||
assert.equal((<any>testComponent).properties[0].value, 'Test Property');
|
||||
done();
|
||||
});
|
||||
// for some reason mocha thinks this test takes 26 seconds even though it doesn't, so it says this failed because it took longer than 2 seconds
|
||||
}).timeout(30000);
|
||||
});
|
||||
266
src/sqltest/parts/disasterRecovery/restoreViewModel.test.ts
Normal file
266
src/sqltest/parts/disasterRecovery/restoreViewModel.test.ts
Normal file
@@ -0,0 +1,266 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
import data = require('data');
|
||||
import * as assert from 'assert';
|
||||
import { ServiceOptionType } from 'sql/parts/connection/common/connectionManagement';
|
||||
import { RestoreViewModel } from 'sql/parts/disasterRecovery/restore/restoreViewModel';
|
||||
|
||||
suite('Restore Dialog view model tests', () => {
|
||||
let option1String = 'option1';
|
||||
let option2Category = 'option2';
|
||||
let option3Boolean = 'option3';
|
||||
let options: { [name: string]: any };
|
||||
let stringServiceOption: data.ServiceOption;
|
||||
let categoryServiceOption: data.ServiceOption;
|
||||
let booleanServiceOption: data.ServiceOption;
|
||||
|
||||
let viewModel: RestoreViewModel;
|
||||
|
||||
let planDetails: { [key: string]: data.RestorePlanDetailInfo };
|
||||
let backupSets: data.DatabaseFileInfo[];
|
||||
|
||||
setup(() => {
|
||||
options = {};
|
||||
planDetails = {};
|
||||
backupSets = [];
|
||||
planDetails['lastBackupTaken'] = {
|
||||
name: 'lastBackupTaken',
|
||||
currentValue: '8/16/2017',
|
||||
isReadOnly: true,
|
||||
isVisible: true,
|
||||
defaultValue: null
|
||||
};
|
||||
|
||||
planDetails['targetDatabaseName'] = {
|
||||
name: 'targetDatabaseName',
|
||||
currentValue: 'db1',
|
||||
isReadOnly: true,
|
||||
isVisible: true,
|
||||
defaultValue: 'db1'
|
||||
};
|
||||
|
||||
planDetails['sourceDatabaseName'] = {
|
||||
name: 'sourceDatabaseName',
|
||||
currentValue: 'dbSource',
|
||||
isReadOnly: true,
|
||||
isVisible: true,
|
||||
defaultValue: 'dbSource'
|
||||
};
|
||||
|
||||
planDetails[option1String] = {
|
||||
name: option1String,
|
||||
currentValue: 'newOptionValue',
|
||||
isReadOnly: true,
|
||||
isVisible: true,
|
||||
defaultValue: 'newDefault'
|
||||
};
|
||||
|
||||
backupSets.push(
|
||||
{
|
||||
properties: [],
|
||||
id: 'file1',
|
||||
isSelected: false
|
||||
},
|
||||
{
|
||||
properties: [],
|
||||
id: 'file2',
|
||||
isSelected: true
|
||||
});
|
||||
|
||||
stringServiceOption = {
|
||||
name: option1String,
|
||||
displayName: 'Option 1',
|
||||
description: null,
|
||||
groupName: null,
|
||||
valueType: ServiceOptionType.string,
|
||||
defaultValue: 'default',
|
||||
objectType: null,
|
||||
categoryValues: null,
|
||||
isRequired: false,
|
||||
isArray: false
|
||||
};
|
||||
|
||||
categoryServiceOption = {
|
||||
name: option2Category,
|
||||
displayName: 'Option 2',
|
||||
description: null,
|
||||
groupName: null,
|
||||
valueType: ServiceOptionType.category,
|
||||
defaultValue: 'catagory1',
|
||||
objectType: null,
|
||||
categoryValues: [{
|
||||
displayName: 'Catagory 1',
|
||||
name: 'catagory1'
|
||||
},
|
||||
{
|
||||
displayName: 'Catagory 2',
|
||||
name: 'catagory2'
|
||||
}],
|
||||
isRequired: false,
|
||||
isArray: false
|
||||
};
|
||||
|
||||
booleanServiceOption = {
|
||||
name: option3Boolean,
|
||||
displayName: 'Option 3',
|
||||
description: null,
|
||||
groupName: null,
|
||||
valueType: ServiceOptionType.boolean,
|
||||
defaultValue: 'true',
|
||||
objectType: null,
|
||||
categoryValues: null,
|
||||
isRequired: false,
|
||||
isArray: false
|
||||
};
|
||||
viewModel = new RestoreViewModel([booleanServiceOption, categoryServiceOption, stringServiceOption]);
|
||||
});
|
||||
|
||||
test('get boolean option type should return correct display value', () => {
|
||||
let falseStringOptionValue = 'False';
|
||||
assert.equal(false, viewModel.getDisplayValue(booleanServiceOption, falseStringOptionValue));
|
||||
|
||||
let falseBooleanOptionValue = false;
|
||||
assert.equal(false, viewModel.getDisplayValue(booleanServiceOption, falseBooleanOptionValue));
|
||||
|
||||
let trueStringOptionValue = 'true';
|
||||
assert.equal(true, viewModel.getDisplayValue(booleanServiceOption, trueStringOptionValue));
|
||||
|
||||
let undefinedOptionValue = undefined;
|
||||
assert.equal(false, viewModel.getDisplayValue(booleanServiceOption, undefinedOptionValue));
|
||||
});
|
||||
|
||||
test('get category option type should return correct display value', () => {
|
||||
let categoryOptionValue = 'catagory2';
|
||||
assert.equal('Catagory 2', viewModel.getDisplayValue(categoryServiceOption, categoryOptionValue));
|
||||
|
||||
let undefinedOptionValue = undefined;
|
||||
assert.equal('Catagory 1', viewModel.getDisplayValue(categoryServiceOption, undefinedOptionValue));
|
||||
});
|
||||
|
||||
test('get string option type should return correct display value', () => {
|
||||
let stringOptionValue = 'string1';
|
||||
assert.equal(stringOptionValue, viewModel.getDisplayValue(stringServiceOption, stringOptionValue));
|
||||
|
||||
let undefinedOptionValue = undefined;
|
||||
assert.equal('', viewModel.getDisplayValue(stringServiceOption, undefinedOptionValue));
|
||||
});
|
||||
|
||||
test('get option meta data should return the correct one', () => {
|
||||
assert.equal(stringServiceOption, viewModel.getOptionMetadata(option1String));
|
||||
assert.equal(categoryServiceOption, viewModel.getOptionMetadata(option2Category));
|
||||
assert.equal(booleanServiceOption, viewModel.getOptionMetadata(option3Boolean));
|
||||
assert.equal(undefined, viewModel.getOptionMetadata('option4'));
|
||||
});
|
||||
|
||||
test('get restore advanced option should return the only the options that have been changed and are different from the default value', () => {
|
||||
viewModel.setOptionValue(option1String, 'default');
|
||||
viewModel.setOptionValue(option2Category, 'Catagory 2');
|
||||
viewModel.setOptionValue(option3Boolean, false);
|
||||
options = {};
|
||||
viewModel.getRestoreAdvancedOptions(options);
|
||||
assert.equal(undefined, options[option1String]);
|
||||
assert.equal('catagory2', options[option2Category]);
|
||||
assert.equal(false, options[option3Boolean]);
|
||||
});
|
||||
|
||||
test('on restore plan response should update all options from restore plan response correctly', () => {
|
||||
let restorePlanResponse: data.RestorePlanResponse = {
|
||||
sessionId: '123',
|
||||
backupSetsToRestore: backupSets,
|
||||
canRestore: true,
|
||||
errorMessage: null,
|
||||
dbFiles: [],
|
||||
databaseNamesFromBackupSets: ['dbSource', 'dbSource2'],
|
||||
planDetails: planDetails
|
||||
};
|
||||
|
||||
viewModel.onRestorePlanResponse(restorePlanResponse);
|
||||
|
||||
// verify that source database, target databasem and last backup get set correctly
|
||||
assert.equal('dbSource', viewModel.sourceDatabaseName);
|
||||
assert.equal('db1', viewModel.targetDatabaseName);
|
||||
assert.equal('8/16/2017', viewModel.lastBackupTaken);
|
||||
|
||||
// verify that advanced options get set correctly
|
||||
options = {};
|
||||
viewModel.getRestoreAdvancedOptions(options);
|
||||
assert.equal('newOptionValue', options[option1String]);
|
||||
|
||||
// verify that selected backup sets get set correctly
|
||||
let selectedBackupSets = viewModel.selectedBackupSets;
|
||||
assert.equal(1, selectedBackupSets.length);
|
||||
assert.equal('file2', selectedBackupSets[0]);
|
||||
});
|
||||
|
||||
|
||||
test('on reset restore options should reset all options', () => {
|
||||
let restorePlanResponse: data.RestorePlanResponse = {
|
||||
sessionId: '123',
|
||||
backupSetsToRestore: backupSets,
|
||||
canRestore: true,
|
||||
errorMessage: null,
|
||||
dbFiles: [],
|
||||
databaseNamesFromBackupSets: ['dbSource', 'dbSource2'],
|
||||
planDetails: planDetails
|
||||
};
|
||||
viewModel.filePath = 'filepath1';
|
||||
viewModel.onRestorePlanResponse(restorePlanResponse);
|
||||
|
||||
//reset restore options
|
||||
viewModel.resetRestoreOptions('db2');
|
||||
|
||||
// verify that file path, source database, target databasem and last backup get set correctly
|
||||
assert.equal('', viewModel.lastBackupTaken);
|
||||
assert.equal('db2', viewModel.sourceDatabaseName);
|
||||
assert.equal('db2', viewModel.targetDatabaseName);
|
||||
assert.equal('', viewModel.lastBackupTaken);
|
||||
assert.equal(0, viewModel.databaseList.length);
|
||||
|
||||
// verify that advanced options get set correctly
|
||||
options = {};
|
||||
viewModel.getRestoreAdvancedOptions(options);
|
||||
assert.equal(undefined, options[option1String]);
|
||||
|
||||
// verify that selected backup sets get set correctly
|
||||
let selectedBackupSets = viewModel.selectedBackupSets;
|
||||
assert.equal(undefined, selectedBackupSets);
|
||||
});
|
||||
|
||||
test('update options with config info should update option correctly', () => {
|
||||
let databaseList = ['db1', 'db2'];
|
||||
let configInfo: { [key: string]: any } = {};
|
||||
configInfo['sourceDatabaseNamesWithBackupSets'] = databaseList;
|
||||
configInfo[option1String] = 'option1 from config info';
|
||||
viewModel.updateOptionWithConfigInfo(configInfo);
|
||||
assert.equal(3, viewModel.databaseList.length);
|
||||
assert.equal('', viewModel.databaseList[0]);
|
||||
assert.equal(databaseList[1], viewModel.databaseList[1]);
|
||||
assert.equal(databaseList[2], viewModel.databaseList[2]);
|
||||
assert.equal('option1 from config info', viewModel.getOptionValue(option1String));
|
||||
|
||||
// verify that the options from get restore advanced options doesn't contain option1String
|
||||
options = {};
|
||||
viewModel.getRestoreAdvancedOptions(options);
|
||||
assert.equal(undefined, options[option1String]);
|
||||
});
|
||||
|
||||
test('on restore from changed should set readHeaderFromMedia and reset the source database names and selected database name correctly', () => {
|
||||
viewModel.databaseList = ['', 'db1', 'db2'];
|
||||
viewModel.sourceDatabaseName = 'sourceDatabase';
|
||||
viewModel.filePath = 'filepath';
|
||||
viewModel.readHeaderFromMedia = false;
|
||||
viewModel.onRestoreFromChanged(true);
|
||||
assert.equal(true, viewModel.readHeaderFromMedia);
|
||||
assert.equal('', viewModel.sourceDatabaseName);
|
||||
assert.equal('', viewModel.filePath);
|
||||
|
||||
viewModel.sourceDatabaseName = 'sourceDatabase2';
|
||||
viewModel.onRestoreFromChanged(false);
|
||||
assert.equal(false, viewModel.readHeaderFromMedia);
|
||||
assert.equal('', viewModel.sourceDatabaseName);
|
||||
});
|
||||
});
|
||||
132
src/sqltest/parts/insights/insightsDialogController.test.ts
Normal file
132
src/sqltest/parts/insights/insightsDialogController.test.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { InsightsDialogController } from 'sql/parts/insights/node/insightsDialogController';
|
||||
import { InsightsDialogModel } from 'sql/parts/insights/common/insightsDialogModel';
|
||||
import QueryRunner from 'sql/parts/query/execution/queryRunner';
|
||||
import { ConnectionManagementService } from 'sql/parts/connection/common/connectionManagementService';
|
||||
import { IInsightsConfigDetails } from 'sql/parts/dashboard/widgets/insights/interfaces';
|
||||
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
||||
|
||||
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
|
||||
|
||||
import { IDbColumn, BatchSummary, QueryExecuteSubsetResult, ResultSetSubset } from 'data';
|
||||
import { EventEmitter } from 'events';
|
||||
import { equal } from 'assert';
|
||||
import { Mock, MockBehavior, It } from 'typemoq';
|
||||
|
||||
const testData: string[][] = [
|
||||
['1', '2', '3', '4'],
|
||||
['5', '6', '7', '8']
|
||||
];
|
||||
|
||||
const testColumns: string[] = [
|
||||
'col1',
|
||||
'col2'
|
||||
];
|
||||
|
||||
suite('Insights Dialog Controller Tests', () => {
|
||||
test('updates correctly with good input', done => {
|
||||
|
||||
let model = new InsightsDialogModel();
|
||||
|
||||
let { runner, complete } = getPrimedQueryRunner(testData, testColumns);
|
||||
|
||||
let instMoq = Mock.ofType(InstantiationService, MockBehavior.Strict);
|
||||
instMoq.setup(x => x.createInstance<QueryRunner>(It.isValue(QueryRunner), It.isAny(), undefined))
|
||||
.returns(() => runner);
|
||||
|
||||
let connMoq = Mock.ofType(ConnectionManagementService, MockBehavior.Strict, {}, {});
|
||||
connMoq.setup(x => x.connect(It.isAny(), It.isAny()))
|
||||
.returns(() => Promise.resolve(undefined));
|
||||
|
||||
let controller = new InsightsDialogController(
|
||||
model,
|
||||
undefined,
|
||||
undefined,
|
||||
instMoq.object,
|
||||
connMoq.object
|
||||
);
|
||||
|
||||
let profile: IConnectionProfile = {
|
||||
serverName: 'server',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: '',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: '',
|
||||
groupId: '',
|
||||
getOptionsKey: () => '',
|
||||
matches: undefined,
|
||||
providerName: '',
|
||||
saveProfile: true,
|
||||
id: '',
|
||||
options: {}
|
||||
};
|
||||
|
||||
controller.update(<IInsightsConfigDetails>{ query: 'query' }, profile).then(() => {
|
||||
// Once we update the controller, listen on when it changes the model and verify the data it
|
||||
// puts in is correct
|
||||
model.onDataChange(() => {
|
||||
for (let i = 0; i < testData.length; i++) {
|
||||
for (let j = 0; j < testData[i].length; j++) {
|
||||
equal(testData[i][j], model.rows[i][j]);
|
||||
}
|
||||
}
|
||||
done();
|
||||
});
|
||||
// Fake the query Runner telling the controller the query is complete
|
||||
complete();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
interface IPrimedQueryRunner {
|
||||
runner: QueryRunner;
|
||||
complete: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a mock of query runner than will recreate what a query runner does to return data
|
||||
*/
|
||||
function getPrimedQueryRunner(data: string[][], columns: string[]): IPrimedQueryRunner {
|
||||
let eventEmitter = new EventEmitter();
|
||||
let querymock = Mock.ofType(QueryRunner, MockBehavior.Strict);
|
||||
querymock.setup(x => x.eventEmitter).returns(x => eventEmitter);
|
||||
querymock.setup(x => x.batchSets).returns(x => {
|
||||
return <Array<BatchSummary>>[
|
||||
{
|
||||
id: 0,
|
||||
resultSetSummaries: [
|
||||
{
|
||||
columnInfo: <Array<IDbColumn>>columns.map(c => { return { columnName: c }; }),
|
||||
id: 0,
|
||||
rowCount: data.length
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
});
|
||||
|
||||
querymock.setup(x => x.getQueryRows(It.isAnyNumber(), It.isAnyNumber(), It.isAnyNumber(), It.isAnyNumber()))
|
||||
.returns(x => Promise.resolve(<QueryExecuteSubsetResult>{
|
||||
resultSubset: <ResultSetSubset>{
|
||||
rowCount: data.length,
|
||||
rows: data.map(r => r.map(c => { return { displayValue: c }; }))
|
||||
}
|
||||
}));
|
||||
|
||||
querymock.setup(x => x.runQuery(It.isAnyString())).returns(x => Promise.resolve());
|
||||
|
||||
let complete = () => {
|
||||
eventEmitter.emit('complete');
|
||||
};
|
||||
|
||||
return {
|
||||
runner: querymock.object,
|
||||
complete
|
||||
};
|
||||
}
|
||||
253
src/sqltest/parts/insights/insightsDialogModel.test.ts
Normal file
253
src/sqltest/parts/insights/insightsDialogModel.test.ts
Normal file
@@ -0,0 +1,253 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { IInsightsLabel, IInsightsConfigDetails } from 'sql/parts/dashboard/widgets/insights/interfaces';
|
||||
import { InsightsDialogModel } from 'sql/parts/insights/common/insightsDialogModel';
|
||||
import { isUndefinedOrNull } from 'vs/base/common/types';
|
||||
|
||||
import * as assert from 'assert';
|
||||
|
||||
suite('Insights Dialog Model Tests', () => {
|
||||
test('does parse condition right', () => {
|
||||
let insightsDialogModel = new InsightsDialogModel();
|
||||
|
||||
let label: IInsightsLabel = {
|
||||
column: undefined,
|
||||
state: [
|
||||
{
|
||||
condition: {
|
||||
if: 'always'
|
||||
},
|
||||
color: 'green'
|
||||
}
|
||||
]
|
||||
} as IInsightsLabel;
|
||||
insightsDialogModel.insight = { label } as IInsightsConfigDetails;
|
||||
insightsDialogModel.rows = [
|
||||
['label1', 'value1'],
|
||||
['label2', 'value2'],
|
||||
['label3', 'value3']
|
||||
];
|
||||
let result = insightsDialogModel.getListResources(0, 1);
|
||||
for (let resource of result) {
|
||||
assert.equal(resource.stateColor, 'green', 'always Condition did not return val as expected');
|
||||
}
|
||||
|
||||
label.state = [
|
||||
{
|
||||
condition: {
|
||||
if: 'equals',
|
||||
equals: 'specific value'
|
||||
},
|
||||
color: 'green'
|
||||
}
|
||||
];
|
||||
|
||||
insightsDialogModel.insight = { label } as IInsightsConfigDetails;
|
||||
insightsDialogModel.rows = [
|
||||
['label1', 'specific value'],
|
||||
['label2', 'value2'],
|
||||
['label3', 'value3']
|
||||
];
|
||||
result = insightsDialogModel.getListResources(0, 1);
|
||||
assert.equal(result[0].stateColor, 'green', 'always Condition did not return val as expected');
|
||||
assert.equal(isUndefinedOrNull(result[1].stateColor), true, 'always Condition did not return val as expected');
|
||||
assert.equal(isUndefinedOrNull(result[2].stateColor), true, 'always Condition did not return val as expected');
|
||||
|
||||
label.state = [
|
||||
{
|
||||
condition: {
|
||||
if: 'equals',
|
||||
equals: 'specific value'
|
||||
},
|
||||
color: 'green'
|
||||
},
|
||||
{
|
||||
condition: {
|
||||
if: 'equals',
|
||||
equals: 'specific value2'
|
||||
},
|
||||
color: 'red'
|
||||
}
|
||||
];
|
||||
|
||||
insightsDialogModel.insight = { label } as IInsightsConfigDetails;
|
||||
insightsDialogModel.rows = [
|
||||
['label1', 'specific value'],
|
||||
['label2', 'specific value2'],
|
||||
['label3', 'value3']
|
||||
];
|
||||
result = insightsDialogModel.getListResources(0, 1);
|
||||
assert.equal(result[0].stateColor, 'green', 'always Condition did not return val as expected');
|
||||
assert.equal(result[1].stateColor, 'red', 'always Condition did not return val as expected');
|
||||
assert.equal(isUndefinedOrNull(result[2].stateColor), true, 'always Condition did not return val as expected');
|
||||
|
||||
label.state = [
|
||||
{
|
||||
condition: {
|
||||
if: 'greaterThan',
|
||||
equals: '2'
|
||||
},
|
||||
color: 'green'
|
||||
},
|
||||
{
|
||||
condition: {
|
||||
if: 'equals',
|
||||
equals: 'specific value2'
|
||||
},
|
||||
color: 'red'
|
||||
}
|
||||
];
|
||||
|
||||
insightsDialogModel.insight = { label } as IInsightsConfigDetails;
|
||||
insightsDialogModel.rows = [
|
||||
['label1', '3'],
|
||||
['label2', 'specific value2'],
|
||||
['label3', 'value3']
|
||||
];
|
||||
result = insightsDialogModel.getListResources(0, 1);
|
||||
assert.equal(result[0].stateColor, 'green', 'always Condition did not return val as expected');
|
||||
assert.equal(result[1].stateColor, 'red', 'always Condition did not return val as expected');
|
||||
assert.equal(isUndefinedOrNull(result[2].stateColor), true, 'always Condition did not return val as expected');
|
||||
|
||||
label.state = [
|
||||
{
|
||||
condition: {
|
||||
if: 'greaterThanOrEquals',
|
||||
equals: '2'
|
||||
},
|
||||
color: 'green'
|
||||
},
|
||||
{
|
||||
condition: {
|
||||
if: 'equals',
|
||||
equals: 'specific value2'
|
||||
},
|
||||
color: 'red'
|
||||
}
|
||||
];
|
||||
|
||||
insightsDialogModel.insight = { label } as IInsightsConfigDetails;
|
||||
insightsDialogModel.rows = [
|
||||
['label1', '2'],
|
||||
['label2', 'specific value2'],
|
||||
['label3', 'value3']
|
||||
];
|
||||
result = insightsDialogModel.getListResources(0, 1);
|
||||
assert.equal(result[0].stateColor, 'green', 'always Condition did not return val as expected');
|
||||
assert.equal(result[1].stateColor, 'red', 'always Condition did not return val as expected');
|
||||
assert.equal(isUndefinedOrNull(result[2].stateColor), true, 'always Condition did not return val as expected');
|
||||
|
||||
label.state = [
|
||||
{
|
||||
condition: {
|
||||
if: 'lessThan',
|
||||
equals: '8'
|
||||
},
|
||||
color: 'green'
|
||||
},
|
||||
{
|
||||
condition: {
|
||||
if: 'equals',
|
||||
equals: 'specific value2'
|
||||
},
|
||||
color: 'red'
|
||||
}
|
||||
];
|
||||
|
||||
insightsDialogModel.insight = { label } as IInsightsConfigDetails;
|
||||
insightsDialogModel.rows = [
|
||||
['label1', '5'],
|
||||
['label2', 'specific value2'],
|
||||
['label3', 'value3']
|
||||
];
|
||||
result = insightsDialogModel.getListResources(0, 1);
|
||||
assert.equal(result[0].stateColor, 'green', 'always Condition did not return val as expected');
|
||||
assert.equal(result[1].stateColor, 'red', 'always Condition did not return val as expected');
|
||||
assert.equal(isUndefinedOrNull(result[2].stateColor), true, 'always Condition did not return val as expected');
|
||||
|
||||
label.state = [
|
||||
{
|
||||
condition: {
|
||||
if: 'lessThanOrEquals',
|
||||
equals: '8'
|
||||
},
|
||||
color: 'green'
|
||||
},
|
||||
{
|
||||
condition: {
|
||||
if: 'equals',
|
||||
equals: 'specific value2'
|
||||
},
|
||||
color: 'red'
|
||||
}
|
||||
];
|
||||
|
||||
insightsDialogModel.insight = { label } as IInsightsConfigDetails;
|
||||
insightsDialogModel.rows = [
|
||||
['label1', '8'],
|
||||
['label2', 'specific value2'],
|
||||
['label3', 'value3']
|
||||
];
|
||||
result = insightsDialogModel.getListResources(0, 1);
|
||||
assert.equal(result[0].stateColor, 'green', 'always Condition did not return val as expected');
|
||||
assert.equal(result[1].stateColor, 'red', 'always Condition did not return val as expected');
|
||||
assert.equal(isUndefinedOrNull(result[2].stateColor), true, 'always Condition did not return val as expected');
|
||||
|
||||
label.state = [
|
||||
{
|
||||
condition: {
|
||||
if: 'notEquals',
|
||||
equals: '9'
|
||||
},
|
||||
color: 'green'
|
||||
},
|
||||
{
|
||||
condition: {
|
||||
if: 'equals',
|
||||
equals: 'specific value2'
|
||||
},
|
||||
color: 'red'
|
||||
}
|
||||
];
|
||||
|
||||
insightsDialogModel.insight = { label } as IInsightsConfigDetails;
|
||||
insightsDialogModel.rows = [
|
||||
['label1', '8'],
|
||||
['label2', '9'],
|
||||
['label3', 'value3']
|
||||
];
|
||||
result = insightsDialogModel.getListResources(0, 1);
|
||||
assert.equal(result[0].stateColor, 'green', 'always Condition did not return val as expected');
|
||||
assert.equal(isUndefinedOrNull(result[1].stateColor), true, 'always Condition did not return val as expected');
|
||||
assert.equal(result[2].stateColor, 'green', 'always Condition did not return val as expected');
|
||||
|
||||
label.state = [
|
||||
{
|
||||
condition: {
|
||||
if: 'notEquals',
|
||||
equals: '9'
|
||||
},
|
||||
color: 'green'
|
||||
},
|
||||
{
|
||||
condition: {
|
||||
if: 'always'
|
||||
},
|
||||
color: 'red'
|
||||
}
|
||||
];
|
||||
|
||||
insightsDialogModel.insight = { label } as IInsightsConfigDetails;
|
||||
insightsDialogModel.rows = [
|
||||
['label1', '8'],
|
||||
['label2', 'specific value2'],
|
||||
['label3', 'value3']
|
||||
];
|
||||
result = insightsDialogModel.getListResources(0, 1);
|
||||
assert.equal(result[0].stateColor, 'green', 'always Condition did not return val as expected');
|
||||
assert.equal(result[1].stateColor, 'green', 'always Condition did not return val as expected');
|
||||
assert.equal(result[2].stateColor, 'green', 'always Condition did not return val as expected');
|
||||
});
|
||||
});
|
||||
567
src/sqltest/parts/query/editor/queryActions.test.ts
Normal file
567
src/sqltest/parts/query/editor/queryActions.test.ts
Normal file
@@ -0,0 +1,567 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
|
||||
import { ISelectionData } from 'data';
|
||||
|
||||
import {
|
||||
IConnectionManagementService,
|
||||
IConnectionParams,
|
||||
INewConnectionParams,
|
||||
ConnectionType,
|
||||
RunQueryOnConnectionMode
|
||||
} from 'sql/parts/connection/common/connectionManagement';
|
||||
import { ConnectionDialogService } from 'sql/parts/connection/connectionDialog/connectionDialogService';
|
||||
import {
|
||||
RunQueryAction, CancelQueryAction, ListDatabasesActionItem,
|
||||
DisconnectDatabaseAction, ConnectDatabaseAction, QueryTaskbarAction
|
||||
} from 'sql/parts/query/execution/queryActions';
|
||||
import { QueryInput } from 'sql/parts/query/common/queryInput';
|
||||
import { QueryEditor } from 'sql/parts/query/editor/queryEditor';
|
||||
import { QueryModelService } from 'sql/parts/query/execution/queryModelService';
|
||||
import { ConnectionManagementService } from 'sql/parts/connection/common/connectionManagementService';
|
||||
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
||||
|
||||
import { TestThemeService } from 'sqltest/stubs/themeTestService';
|
||||
|
||||
import * as TypeMoq from 'typemoq';
|
||||
import * as assert from 'assert';
|
||||
|
||||
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>;
|
||||
|
||||
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; });
|
||||
|
||||
// Setup a reusable mock QueryEditor
|
||||
editor = TypeMoq.Mock.ofType(QueryEditor, TypeMoq.MockBehavior.Strict, undefined, new TestThemeService());
|
||||
editor.setup(x => x.connectedUri).returns(() => testUri);
|
||||
editor.setup(x => x.currentQueryInput).returns(() => testQueryInput.object);
|
||||
editor.setup(x => x.uri).returns(() => testUri);
|
||||
|
||||
editor.setup(x => x.getSelection()).returns(() => undefined);
|
||||
editor.setup(x => x.getSelection(false)).returns(() => undefined);
|
||||
editor.setup(x => x.isSelectionEmpty()).returns(() => false);
|
||||
});
|
||||
|
||||
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, {}, {});
|
||||
connectionManagementService.setup(x => x.isConnected(TypeMoq.It.isAnyString())).returns(() => isConnectedReturnValue);
|
||||
|
||||
// ... Create an editor
|
||||
let editor = TypeMoq.Mock.ofType(QueryEditor, TypeMoq.MockBehavior.Loose, undefined, new TestThemeService());
|
||||
editor.setup(x => x.currentQueryInput).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 calledRunQuery: boolean = false;
|
||||
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))
|
||||
.callback((service: IConnectionManagementService, params: INewConnectionParams) => {
|
||||
connectionParams = params;
|
||||
countCalledShowDialog++;
|
||||
})
|
||||
.returns(() => TPromise.as(none));
|
||||
|
||||
// ... Mock "isConnected" in ConnectionManagementService
|
||||
let connectionManagementService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, {}, {}, 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())).callback(() => {
|
||||
calledRunQuery = true;
|
||||
});
|
||||
|
||||
// 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 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, 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.currentQueryInput, '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++;
|
||||
});
|
||||
let queryEditor: TypeMoq.Mock<QueryEditor> = TypeMoq.Mock.ofType(QueryEditor, TypeMoq.MockBehavior.Strict, undefined, new TestThemeService());
|
||||
queryEditor.setup(x => x.currentQueryInput).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', (done) => {
|
||||
|
||||
/// 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))
|
||||
.callback((service: IConnectionManagementService, params: INewConnectionParams) => {
|
||||
showDialogConnectionParams = params;
|
||||
countCalledShowDialog++;
|
||||
})
|
||||
.returns(() => TPromise.as(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++;
|
||||
});
|
||||
|
||||
// ... Mock "getSelection" in QueryEditor
|
||||
let queryEditor: TypeMoq.Mock<QueryEditor> = TypeMoq.Mock.ofType(QueryEditor, TypeMoq.MockBehavior.Loose, undefined, new TestThemeService());
|
||||
queryEditor.setup(x => x.currentQueryInput).returns(() => queryInput.object);
|
||||
queryEditor.setup(x => x.getSelection()).returns(() => {
|
||||
return selectionToReturnInGetSelection;
|
||||
});
|
||||
|
||||
// ... Mock "isConnected" in ConnectionManagementService
|
||||
let connectionManagementService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, {}, {}, 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');
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
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))
|
||||
.callback((service: IConnectionManagementService, params: INewConnectionParams) => {
|
||||
connectionParams = params;
|
||||
countCalledShowDialog++;
|
||||
})
|
||||
.returns(() => TPromise.as(none));
|
||||
|
||||
// ... Mock "isConnected" in ConnectionManagementService
|
||||
let connectionManagementService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, {}, {}, 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.currentQueryInput, '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.currentQueryInput, '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))
|
||||
.callback((service: IConnectionManagementService, params: INewConnectionParams) => {
|
||||
calledShowDialog++;
|
||||
connectionParams = params;
|
||||
})
|
||||
.returns(() => TPromise.as(none));
|
||||
|
||||
// ... Mock "isConnected" in ConnectionManagementService
|
||||
let connectionManagementService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, {}, {}, 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 conneciton 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.currentQueryInput, '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.currentQueryInput, '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, undefined, undefined);
|
||||
|
||||
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, null, null, null);
|
||||
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, {}, {});
|
||||
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, null, null, null);
|
||||
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, {}, {});
|
||||
cms.callBase = true;
|
||||
cms.setup(x => x.onConnectionChanged).returns(() => dbChangedEmitter.event);
|
||||
|
||||
// ... Create a database dropdown
|
||||
let listItem = new ListDatabasesActionItem(editor.object, undefined, cms.object, null, null, null);
|
||||
|
||||
// If: I raise a connection changed event
|
||||
let eventParams = <IConnectionParams> {
|
||||
connectionProfile: {
|
||||
databaseName: 'foobarbaz'
|
||||
},
|
||||
connectionUri: editor.object.uri
|
||||
};
|
||||
dbChangedEmitter.fire(eventParams);
|
||||
|
||||
// Then:
|
||||
// ... The connection should have changed to the provided database
|
||||
assert.equal(listItem.currentDatabaseName, eventParams.connectionProfile.databaseName);
|
||||
});
|
||||
});
|
||||
391
src/sqltest/parts/query/editor/queryEditor.test.ts
Normal file
391
src/sqltest/parts/query/editor/queryEditor.test.ts
Normal file
@@ -0,0 +1,391 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
|
||||
import { IMessageService } from 'vs/platform/message/common/message';
|
||||
import { TestMessageService, TestEditorGroupService } from 'vs/workbench/test/workbenchTestServices';
|
||||
import { IEditorDescriptor, EditorInput } from 'vs/workbench/common/editor';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { Memento } from 'vs/workbench/common/memento';
|
||||
import { Builder } from 'vs/base/browser/builder';
|
||||
import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput';
|
||||
|
||||
import { QueryResultsInput } from 'sql/parts/query/common/queryResultsInput';
|
||||
import { QueryEditor } from 'sql/parts/query/editor/queryEditor';
|
||||
import { QueryModelService } from 'sql/parts/query/execution/queryModelService';
|
||||
import { QueryInput } from 'sql/parts/query/common/queryInput';
|
||||
import { INewConnectionParams, ConnectionType, RunQueryOnConnectionMode } from 'sql/parts/connection/common/connectionManagement';
|
||||
import { ConnectionManagementService } from 'sql/parts/connection/common/connectionManagementService';
|
||||
import { RunQueryAction, ListDatabasesActionItem } from 'sql/parts/query/execution/queryActions';
|
||||
import { EditorDescriptorService } from 'sql/parts/query/editor/editorDescriptorService';
|
||||
|
||||
import { TestThemeService } from 'sqltest/stubs/themeTestService';
|
||||
|
||||
import * as TypeMoq from 'typemoq';
|
||||
import * as assert from 'assert';
|
||||
|
||||
suite('SQL QueryEditor Tests', () => {
|
||||
let queryModelService: QueryModelService;
|
||||
let instantiationService: TypeMoq.Mock<InstantiationService>;
|
||||
let themeService: TestThemeService = new TestThemeService();
|
||||
let messageService: TypeMoq.Mock<IMessageService>;
|
||||
let editorDescriptorService: TypeMoq.Mock<EditorDescriptorService>;
|
||||
let connectionManagementService: TypeMoq.Mock<ConnectionManagementService>;
|
||||
let memento: TypeMoq.Mock<Memento>;
|
||||
|
||||
let queryInput: QueryInput;
|
||||
let queryInput2: QueryInput;
|
||||
let parentBuilder: Builder;
|
||||
let mockEditor: any;
|
||||
|
||||
let getQueryEditor = function (): QueryEditor {
|
||||
return new QueryEditor(
|
||||
undefined,
|
||||
themeService,
|
||||
instantiationService.object,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
editorDescriptorService.object,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined);
|
||||
};
|
||||
|
||||
setup(() => {
|
||||
// Setup DOM elements
|
||||
let element = DOM.$('queryEditorParent');
|
||||
parentBuilder = new Builder(element);
|
||||
|
||||
// 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 TPromise((resolve) => resolve(mockEditor));
|
||||
});
|
||||
instantiationService.setup(x => x.createInstance(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns((input) => {
|
||||
return new TPromise((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, action, connectionManagementService.object, undefined, undefined, undefined);
|
||||
}
|
||||
}
|
||||
// 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; }
|
||||
};
|
||||
editorDescriptorService = TypeMoq.Mock.ofType(EditorDescriptorService, TypeMoq.MockBehavior.Loose);
|
||||
editorDescriptorService.setup(x => x.getEditor(TypeMoq.It.isAny())).returns(() => descriptor);
|
||||
|
||||
// Create a QueryInput
|
||||
let filePath = 'someFile.sql';
|
||||
let uri: URI = URI.parse(filePath);
|
||||
let fileInput = new UntitledEditorInput(uri, false, '', '', '', instantiationService.object, undefined, undefined, undefined);
|
||||
let queryResultsInput: QueryResultsInput = new QueryResultsInput(uri.fsPath);
|
||||
queryInput = new QueryInput('first', 'first', fileInput, queryResultsInput, undefined, undefined, undefined, undefined);
|
||||
|
||||
// Create a QueryInput to compare to the previous one
|
||||
let filePath2 = 'someFile2.sql';
|
||||
let uri2: URI = URI.parse(filePath2);
|
||||
let fileInput2 = new UntitledEditorInput(uri2, false, '', '', '', instantiationService.object, undefined, undefined, undefined);
|
||||
let queryResultsInput2: QueryResultsInput = new QueryResultsInput(uri2.fsPath);
|
||||
queryInput2 = new QueryInput('second', 'second', fileInput2, queryResultsInput2, undefined, undefined, undefined, undefined);
|
||||
|
||||
// Mock IMessageService
|
||||
messageService = TypeMoq.Mock.ofType(TestMessageService, TypeMoq.MockBehavior.Loose);
|
||||
|
||||
// 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);
|
||||
connectionManagementService.callBase = true;
|
||||
connectionManagementService.setup(x => x.isConnected(TypeMoq.It.isAny())).returns(() => false);
|
||||
|
||||
// Create a QueryModelService
|
||||
queryModelService = new QueryModelService(instantiationService.object, messageService.object);
|
||||
});
|
||||
|
||||
test('createEditor creates only the taskbar', (done) => {
|
||||
// If I call createEditor
|
||||
let editor: QueryEditor = getQueryEditor();
|
||||
editor.createEditor(parentBuilder);
|
||||
|
||||
// The taskbar should be created
|
||||
assert.equal(!!editor.taskbar, true);
|
||||
assert.equal(!!editor.taskbarContainer, true);
|
||||
|
||||
// But Nothing else should be created
|
||||
assert.equal(!!editor.getContainer(), false);
|
||||
assert.equal(!!editor.sqlEditor, false);
|
||||
assert.equal(!!editor.sqlEditorContainer, false);
|
||||
assert.equal(!!editor.resultsEditor, false);
|
||||
assert.equal(!!editor.resultsEditorContainer, false);
|
||||
assert.equal(!!editor.sash, false);
|
||||
assert.equal(!!editor._isResultsEditorVisible(), false);
|
||||
done();
|
||||
});
|
||||
|
||||
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,
|
||||
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);
|
||||
queryConnectionService.callBase = true;
|
||||
|
||||
// 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 TPromise((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, action, queryConnectionService.object, undefined, undefined, undefined);
|
||||
return item;
|
||||
}
|
||||
// Default
|
||||
return new RunQueryAction(undefined, undefined, undefined);
|
||||
});
|
||||
|
||||
let fileInput = new UntitledEditorInput(URI.parse('testUri'), false, '', '', '', instantiationService.object, undefined, undefined, undefined);
|
||||
queryModelService = TypeMoq.Mock.ofType(QueryModelService, TypeMoq.MockBehavior.Loose, undefined, undefined);
|
||||
queryModelService.callBase = true;
|
||||
queryInput = new QueryInput(
|
||||
'testUri',
|
||||
'',
|
||||
fileInput,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
queryModelService.object,
|
||||
undefined
|
||||
);
|
||||
});
|
||||
|
||||
test('Taskbar buttons are set correctly upon standard load', (done) => {
|
||||
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.runQueryEnabled, true, 'runQueryAction button should be enabled');
|
||||
assert.equal(queryInput.cancelQueryEnabled, false, 'cancelQueryAction button should not be enabled');
|
||||
assert.equal(queryInput.connectEnabled, true, 'connectDatabaseAction button should be enabled');
|
||||
assert.equal(queryInput.disconnectEnabled, false, 'disconnectDatabaseAction button should not be enabled');
|
||||
assert.equal(queryInput.changeConnectionEnabled, false, 'changeConnectionAction button should not be enabled');
|
||||
assert.equal(queryInput.listDatabasesConnected, false);
|
||||
done();
|
||||
});
|
||||
|
||||
test('Taskbar buttons are set correctly upon connect', (done) => {
|
||||
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.runQueryEnabled, true, 'runQueryAction button should be enabled');
|
||||
assert.equal(queryInput.cancelQueryEnabled, false, 'cancelQueryAction button should not be enabled');
|
||||
assert.equal(queryInput.connectEnabled, false, 'connectDatabaseAction button should not be enabled');
|
||||
assert.equal(queryInput.disconnectEnabled, true, 'disconnectDatabaseAction button should be enabled');
|
||||
assert.equal(queryInput.changeConnectionEnabled, true, 'changeConnectionAction button should be enabled');
|
||||
assert.equal(queryInput.listDatabasesConnected, true);
|
||||
done();
|
||||
});
|
||||
test('Test that we attempt to dispose query when the queryInput is disposed', (done) => {
|
||||
let queryResultsInput = new QueryResultsInput('testUri');
|
||||
queryInput['_results'] = queryResultsInput;
|
||||
queryInput.dispose();
|
||||
queryModelService.verify(x => x.disposeQuery(TypeMoq.It.isAnyString()), TypeMoq.Times.once());
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,93 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
||||
import { ServerTreeView } from 'sql/parts/registeredServer/viewlet/serverTreeView';
|
||||
import { ConnectionManagementService } from 'sql/parts/connection/common/connectionManagementService';
|
||||
|
||||
import { Tree } from 'vs/base/parts/tree/browser/treeImpl';
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
|
||||
import * as TypeMoq from 'typemoq';
|
||||
|
||||
suite('ServerTreeView onAddConnectionProfile handler tests', () => {
|
||||
|
||||
let serverTreeView: ServerTreeView;
|
||||
let mockTree: TypeMoq.Mock<Tree>;
|
||||
let mockRefreshTreeMethod: TypeMoq.Mock<Function>;
|
||||
|
||||
setup(() => {
|
||||
let instantiationService = new TestInstantiationService();
|
||||
let mockConnectionManagementService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Strict, {}, {});
|
||||
mockConnectionManagementService.setup(x => x.getConnectionGroups()).returns(x => []);
|
||||
serverTreeView = new ServerTreeView(mockConnectionManagementService.object, instantiationService, undefined, undefined, undefined);
|
||||
let tree = <Tree>{
|
||||
clearSelection() { },
|
||||
getSelection() { },
|
||||
select(selection) { },
|
||||
reveal(reveal) { }
|
||||
};
|
||||
mockTree = TypeMoq.Mock.ofInstance(tree);
|
||||
(serverTreeView as any)._tree = mockTree.object;
|
||||
mockRefreshTreeMethod = TypeMoq.Mock.ofType(Function);
|
||||
(serverTreeView as any).refreshTree = mockRefreshTreeMethod.object;
|
||||
mockTree.setup(x => x.clearSelection());
|
||||
mockTree.setup(x => x.select(TypeMoq.It.isAny()));
|
||||
});
|
||||
|
||||
function runAddConnectionProfileHandler(oldSelection, newProfile) {
|
||||
mockTree.setup(x => x.getSelection()).returns(() => [oldSelection] || []);
|
||||
(serverTreeView as any).handleAddConnectionProfile(newProfile);
|
||||
}
|
||||
|
||||
test('onAddConnectionProfile handler selects the new profile when no profile is already selected', () => {
|
||||
let newProfile = <IConnectionProfile>{
|
||||
id: 'test_connection'
|
||||
};
|
||||
runAddConnectionProfileHandler(undefined, newProfile);
|
||||
mockRefreshTreeMethod.verify(x => x(), TypeMoq.Times.once());
|
||||
mockTree.verify(x => x.clearSelection(), TypeMoq.Times.never());
|
||||
mockTree.verify(x => x.select(TypeMoq.It.is(profile => profile === newProfile)), TypeMoq.Times.once());
|
||||
});
|
||||
|
||||
test('onAddConnectionProfile handler selects the new profile when a different profile is already selected', () => {
|
||||
let oldProfile = <IConnectionProfile>{
|
||||
id: 'old_connection'
|
||||
};
|
||||
let newProfile = <IConnectionProfile>{
|
||||
id: 'test_connection'
|
||||
};
|
||||
runAddConnectionProfileHandler(oldProfile, newProfile);
|
||||
mockRefreshTreeMethod.verify(x => x(), TypeMoq.Times.once());
|
||||
mockTree.verify(x => x.clearSelection(), TypeMoq.Times.once());
|
||||
mockTree.verify(x => x.select(TypeMoq.It.is(profile => profile === newProfile)), TypeMoq.Times.once());
|
||||
});
|
||||
|
||||
test('onAddConnectionProfile handler does not clear the selection when the new profile is already selected', () => {
|
||||
let selectionId = 'test_connection';
|
||||
let oldProfile = <IConnectionProfile>{
|
||||
id: selectionId
|
||||
};
|
||||
let newProfile = <IConnectionProfile>{
|
||||
id: selectionId
|
||||
};
|
||||
runAddConnectionProfileHandler(oldProfile, newProfile);
|
||||
mockRefreshTreeMethod.verify(x => x(), TypeMoq.Times.once());
|
||||
mockTree.verify(x => x.clearSelection(), TypeMoq.Times.never());
|
||||
mockTree.verify(x => x.select(TypeMoq.It.isAny()), TypeMoq.Times.never());
|
||||
});
|
||||
|
||||
test('onAddConnectionProfile handler does not clear the previously selected profile if there is no new one', () => {
|
||||
let oldProfile = <IConnectionProfile>{
|
||||
id: 'test_connection'
|
||||
};
|
||||
runAddConnectionProfileHandler(oldProfile, undefined);
|
||||
mockRefreshTreeMethod.verify(x => x(), TypeMoq.Times.once());
|
||||
mockTree.verify(x => x.clearSelection(), TypeMoq.Times.never());
|
||||
mockTree.verify(x => x.select(TypeMoq.It.isAny()), TypeMoq.Times.never());
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,508 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as data from 'data';
|
||||
import * as TypeMoq from 'typemoq';
|
||||
import AccountStore from 'sql/services/accountManagement/accountStore';
|
||||
import { SqlOAuthTestService } from 'sqltest/stubs/sqlOauthServiceStub';
|
||||
import { AccountDialogController } from 'sql/parts/accountManagement/accountDialog/accountDialogController';
|
||||
import { AccountManagementService } from 'sql/services/accountManagement/accountManagementService';
|
||||
import { AccountAdditionResult, AccountProviderAddedEventParams, UpdateAccountListEventParams } from 'sql/services/accountManagement/eventTypes';
|
||||
import { IAccountStore } from 'sql/services/accountManagement/interfaces';
|
||||
import { AccountProviderStub } from 'sqltest/stubs/accountManagementStubs';
|
||||
import { EventVerifierSingle } from 'sqltest/utils/eventVerifier';
|
||||
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
|
||||
|
||||
// SUITE CONSTANTS /////////////////////////////////////////////////////////
|
||||
const hasAccountProvider: data.AccountProviderMetadata = {
|
||||
id: 'hasAccounts',
|
||||
displayName: 'Provider with Accounts'
|
||||
};
|
||||
const noAccountProvider: data.AccountProviderMetadata = {
|
||||
id: 'noAccounts',
|
||||
displayName: 'Provider without Accounts'
|
||||
};
|
||||
|
||||
const account: data.Account = {
|
||||
key: {
|
||||
providerId: hasAccountProvider.id,
|
||||
accountId: 'testAccount1'
|
||||
},
|
||||
displayInfo: {
|
||||
displayName: 'Test Account 1',
|
||||
contextualLogo: {light: '', dark: ''},
|
||||
contextualDisplayName: 'Azure Account'
|
||||
},
|
||||
isStale: false,
|
||||
properties: {}
|
||||
};
|
||||
const accountList: data.Account[] = [account];
|
||||
|
||||
suite('Account Management Service Tests:', () => {
|
||||
test('Constructor', () => {
|
||||
// If: I construct an account management service
|
||||
let ams = getTestState().accountManagementService;
|
||||
|
||||
// Then:
|
||||
// ... It should be created successfully
|
||||
// ... Events should be available to register
|
||||
assert.ok(ams.addAccountProviderEvent);
|
||||
assert.ok(ams.removeAccountProviderEvent);
|
||||
assert.ok(ams.updateAccountListEvent);
|
||||
});
|
||||
|
||||
test('Add account - provider exists, account does not exist', done => {
|
||||
// Setup:
|
||||
// ... Create account management service with a provider
|
||||
let state = getTestState();
|
||||
let mockProvider = getMockAccountProvider();
|
||||
state.accountManagementService._providers[hasAccountProvider.id] = {
|
||||
accounts: [],
|
||||
provider: mockProvider.object,
|
||||
metadata: hasAccountProvider
|
||||
};
|
||||
|
||||
// ... Add add/update handler to the account store that says account was new
|
||||
state.mockAccountStore.setup(x => x.addOrUpdate(TypeMoq.It.isValue(account)))
|
||||
.returns(() => Promise.resolve(<AccountAdditionResult>{
|
||||
accountModified: false,
|
||||
accountAdded: true,
|
||||
changedAccount: account
|
||||
}));
|
||||
|
||||
// If: I ask to add an account
|
||||
return state.accountManagementService.addAccount(hasAccountProvider.id)
|
||||
.then(result => {
|
||||
// Then:
|
||||
// ... The provider should have been prompted
|
||||
mockProvider.verify(x => x.prompt(), TypeMoq.Times.once());
|
||||
|
||||
// ... The account store should have added/updated
|
||||
state.mockAccountStore.verify(x => x.addOrUpdate(TypeMoq.It.isValue(account)), TypeMoq.Times.once());
|
||||
|
||||
// ... The account list change should have been fired
|
||||
state.eventVerifierUpdate.assertFiredWithVerify(param => {
|
||||
assert.equal(param.providerId, hasAccountProvider.id);
|
||||
assert.ok(Array.isArray(param.accountList));
|
||||
assert.equal(param.accountList.length, 1);
|
||||
assert.equal(param.accountList[0], account);
|
||||
});
|
||||
|
||||
// ... The returned account should be the new one
|
||||
assert.equal(result, account);
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
err => done(err)
|
||||
);
|
||||
});
|
||||
|
||||
test('Add account - provider exists, account exists', done => {
|
||||
// Setup:
|
||||
// ... Create account management service with a provider
|
||||
let state = getTestState();
|
||||
let mockProvider = getMockAccountProvider();
|
||||
state.accountManagementService._providers[hasAccountProvider.id] = {
|
||||
accounts: [account],
|
||||
provider: mockProvider.object,
|
||||
metadata: hasAccountProvider
|
||||
};
|
||||
|
||||
// ... Add add/update handler to the account store that says account was not new
|
||||
state.mockAccountStore.setup(x => x.addOrUpdate(TypeMoq.It.isValue(account)))
|
||||
.returns(() => Promise.resolve(<AccountAdditionResult>{
|
||||
accountModified: true,
|
||||
accountAdded: false,
|
||||
changedAccount: account
|
||||
}));
|
||||
|
||||
// If: I ask to add an account
|
||||
return state.accountManagementService.addAccount(hasAccountProvider.id)
|
||||
.then(result => {
|
||||
// Then:
|
||||
// ... The provider should have been prompted
|
||||
mockProvider.verify(x => x.prompt(), TypeMoq.Times.once());
|
||||
|
||||
// ... The account store should have added/updated
|
||||
state.mockAccountStore.verify(x => x.addOrUpdate(TypeMoq.It.isValue(account)), TypeMoq.Times.once());
|
||||
|
||||
// ... The account list change should have been fired
|
||||
state.eventVerifierUpdate.assertFiredWithVerify(param => {
|
||||
assert.equal(param.providerId, hasAccountProvider.id);
|
||||
assert.ok(Array.isArray(param.accountList));
|
||||
assert.equal(param.accountList.length, 1);
|
||||
assert.equal(param.accountList[0], account);
|
||||
});
|
||||
|
||||
// ... The returned account should be the new one
|
||||
assert.equal(result, account);
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
err => done(err)
|
||||
);
|
||||
});
|
||||
|
||||
test('Add account - provider doesn\'t exist', done => {
|
||||
// Setup: Create account management service
|
||||
let ams = getTestState().accountManagementService;
|
||||
|
||||
// If: I add an account when the provider doesn't exist
|
||||
// Then: It should be rejected
|
||||
ams.addAccount('doesNotExist')
|
||||
.then(
|
||||
() => done('Promise resolved when it should have rejected'),
|
||||
() => done()
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
test('Get account provider metadata - providers exist', done => {
|
||||
// Setup: Create account management service with a provider
|
||||
let state = getTestState();
|
||||
state.accountManagementService._providers[noAccountProvider.id] = {
|
||||
accounts: [],
|
||||
provider: null, // Doesn't matter
|
||||
metadata: noAccountProvider
|
||||
};
|
||||
|
||||
// If: I ask for all the account provider metadata
|
||||
return state.accountManagementService.getAccountProviderMetadata()
|
||||
.then(result => {
|
||||
// Then: The list should have the one account provider in it
|
||||
assert.ok(Array.isArray(result));
|
||||
assert.equal(result.length, 1);
|
||||
assert.equal(result[0], noAccountProvider);
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
err => done(err)
|
||||
);
|
||||
});
|
||||
|
||||
test('Get account provider metadata - no providers', done => {
|
||||
// Setup: Create account management service
|
||||
let ams = getTestState().accountManagementService;
|
||||
|
||||
// If: I ask for account provider metadata when there isn't any providers
|
||||
ams.getAccountProviderMetadata()
|
||||
.then(result => {
|
||||
// Then: The results should be an empty array
|
||||
assert.ok(Array.isArray(result));
|
||||
assert.equal(result.length, 0);
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
err => done(err)
|
||||
);
|
||||
});
|
||||
|
||||
test('Get accounts by provider - provider does not exist', done => {
|
||||
// Setup: Create account management service
|
||||
let ams = getTestState().accountManagementService;
|
||||
|
||||
// If: I get accounts when the provider doesn't exist
|
||||
// Then: It should be rejected
|
||||
ams.getAccountsForProvider('doesNotExist')
|
||||
.then(
|
||||
() => done('Promise resolved when it should have rejected'),
|
||||
() => done()
|
||||
);
|
||||
});
|
||||
|
||||
test('Get accounts by provider - provider exists, no accounts', done => {
|
||||
// Setup: Create account management service
|
||||
let ams = getTestState().accountManagementService;
|
||||
ams._providers[noAccountProvider.id] = {
|
||||
accounts: [],
|
||||
provider: null, // Doesn't matter
|
||||
metadata: noAccountProvider
|
||||
};
|
||||
|
||||
// If: I ask for the accounts for a provider with no accounts
|
||||
ams.getAccountsForProvider(noAccountProvider.id)
|
||||
.then(result => {
|
||||
// Then: I should get back an empty array
|
||||
assert.ok(Array.isArray(result));
|
||||
assert.equal(result.length, 0);
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
err => done(err)
|
||||
);
|
||||
});
|
||||
|
||||
test('Get accounts by provider - provider exists, has accounts', done => {
|
||||
// Setup: Create account management service
|
||||
let ams = getTestState().accountManagementService;
|
||||
ams._providers[hasAccountProvider.id] = {
|
||||
accounts: [account],
|
||||
provider: null, // Doesn't matter
|
||||
metadata: hasAccountProvider
|
||||
};
|
||||
|
||||
// If: I ask for the accounts for a provider with accounts
|
||||
ams.getAccountsForProvider(hasAccountProvider.id)
|
||||
.then(result => {
|
||||
// Then: I should get back the list of accounts
|
||||
assert.equal(result, accountList);
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
err => done(err)
|
||||
);
|
||||
});
|
||||
|
||||
test('Remove account - account exists', done => {
|
||||
// Setup:
|
||||
// ... Create account management service and to fake removing an account that exists
|
||||
let state = getTestState();
|
||||
state.mockAccountStore.setup(x => x.remove(TypeMoq.It.isAny()))
|
||||
.returns(() => Promise.resolve(true));
|
||||
|
||||
// ... Register a account provider with the management service
|
||||
let mockProvider = TypeMoq.Mock.ofType<data.AccountProvider>(AccountProviderStub);
|
||||
mockProvider.setup(x => x.clear(TypeMoq.It.isAny())).returns(() => Promise.resolve());
|
||||
state.accountManagementService._providers[hasAccountProvider.id] = {
|
||||
accounts: [account],
|
||||
provider: mockProvider.object,
|
||||
metadata: hasAccountProvider
|
||||
};
|
||||
|
||||
// If: I remove an account that exists
|
||||
state.accountManagementService.removeAccount(account.key)
|
||||
.then( result => {
|
||||
// Then:
|
||||
// ... I should have gotten true back
|
||||
assert.ok(result);
|
||||
|
||||
// ... The account store should have had remove called
|
||||
state.mockAccountStore.verify(x => x.remove(TypeMoq.It.isValue(account.key)), TypeMoq.Times.once());
|
||||
|
||||
// ... The provider should have had clear called
|
||||
mockProvider.verify(x => x.clear(TypeMoq.It.isValue(account.key)), TypeMoq.Times.once());
|
||||
|
||||
// ... The updated account list event should have fired
|
||||
state.eventVerifierUpdate.assertFiredWithVerify((params: UpdateAccountListEventParams) => {
|
||||
assert.equal(params.providerId, hasAccountProvider.id);
|
||||
assert.ok(Array.isArray(params.accountList));
|
||||
assert.equal(params.accountList.length, 0);
|
||||
});
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
err => done(err)
|
||||
);
|
||||
});
|
||||
|
||||
test('Remove account - account doesn\'t exist', done => {
|
||||
// Setup:
|
||||
// ... Create account management service and to fake removing an account that doesn't exist
|
||||
let state = getTestState();
|
||||
state.mockAccountStore.setup(x => x.remove(TypeMoq.It.isAny()))
|
||||
.returns(() => Promise.resolve(false));
|
||||
|
||||
// ... Register a account provider with the management service
|
||||
let mockProvider = getMockAccountProvider();
|
||||
mockProvider.setup(x => x.clear(TypeMoq.It.isAny())).returns(() => Promise.resolve());
|
||||
state.accountManagementService._providers[noAccountProvider.id] = {
|
||||
accounts: [],
|
||||
provider: mockProvider.object,
|
||||
metadata: noAccountProvider
|
||||
};
|
||||
|
||||
// If: I remove an account that doesn't exist
|
||||
let accountKey = {providerId: noAccountProvider.id, accountId: 'foobar'};
|
||||
state.accountManagementService.removeAccount(accountKey)
|
||||
.then(result => {
|
||||
// Then:
|
||||
// ... I should have gotten false back
|
||||
assert.ok(!result);
|
||||
|
||||
// ... The account store should have had remove called
|
||||
state.mockAccountStore.verify(x => x.remove(TypeMoq.It.isValue(accountKey)), TypeMoq.Times.once());
|
||||
|
||||
// ... The provider should have had clear called
|
||||
mockProvider.verify(x => x.clear(TypeMoq.It.isValue(accountKey)), TypeMoq.Times.once());
|
||||
|
||||
// ... The updated account list event should not have fired
|
||||
state.eventVerifierUpdate.assertNotFired();
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
err => done(err)
|
||||
);
|
||||
});
|
||||
|
||||
test('Open account dialog - first call', done => {
|
||||
// Setup:
|
||||
// ... Create account management ervice
|
||||
let state = getTestState();
|
||||
|
||||
// ... Add mocking for instantiating an account dialog controller
|
||||
let mockDialogController = TypeMoq.Mock.ofType(AccountDialogController);
|
||||
mockDialogController.setup(x => x.openAccountDialog());
|
||||
state.instantiationService.setup(x => x.createInstance<AccountDialogController>(TypeMoq.It.isValue(AccountDialogController)))
|
||||
.returns(() => mockDialogController.object);
|
||||
|
||||
// If: I open the account dialog when it doesn't exist
|
||||
state.accountManagementService.openAccountListDialog()
|
||||
.then(() => {
|
||||
// Then:
|
||||
// ... The instantiation service should have been called once
|
||||
state.instantiationService.verify(x => x.createInstance<AccountDialogController>(TypeMoq.It.isValue(AccountDialogController)), TypeMoq.Times.once());
|
||||
|
||||
// ... The dialog should have been opened
|
||||
mockDialogController.verify(x => x.openAccountDialog(), TypeMoq.Times.once());
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
err => done(err)
|
||||
);
|
||||
});
|
||||
|
||||
test('Open account dialog - subsequent calls', done => {
|
||||
// Setup:
|
||||
// ... Create account management ervice
|
||||
let state = getTestState();
|
||||
|
||||
// ... Add mocking for instantiating an account dialog controller
|
||||
let mockDialogController = TypeMoq.Mock.ofType(AccountDialogController);
|
||||
mockDialogController.setup(x => x.openAccountDialog());
|
||||
state.instantiationService.setup(x => x.createInstance<AccountDialogController>(TypeMoq.It.isValue(AccountDialogController)))
|
||||
.returns(() => mockDialogController.object);
|
||||
|
||||
// If: I open the account dialog for a second time
|
||||
state.accountManagementService.openAccountListDialog()
|
||||
.then(() => state.accountManagementService.openAccountListDialog())
|
||||
.then(() => {
|
||||
// Then:
|
||||
// ... The instantiation service should have only been called once
|
||||
state.instantiationService.verify(x => x.createInstance<AccountDialogController>(TypeMoq.It.isValue(AccountDialogController)), TypeMoq.Times.once());
|
||||
|
||||
// ... The dialog should have been opened twice
|
||||
mockDialogController.verify(x => x.openAccountDialog(), TypeMoq.Times.exactly(2));
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
err => done(err)
|
||||
);
|
||||
});
|
||||
|
||||
// test('Perform oauth - success', done => {
|
||||
// TODO: implement this test properly once we remove direct IPC calls
|
||||
// });
|
||||
|
||||
test('Register provider - success', done => {
|
||||
// Setup:
|
||||
// ... Create ams, account store that will accept account add/update
|
||||
let mocks = getTestState();
|
||||
mocks.mockAccountStore.setup(x => x.addOrUpdate(TypeMoq.It.isAny()))
|
||||
.returns(() => Promise.resolve(undefined));
|
||||
|
||||
// ... Create mock account provider
|
||||
let mockProvider = getMockAccountProvider();
|
||||
|
||||
// If: I register a new provider
|
||||
mocks.accountManagementService.registerProvider(noAccountProvider, mockProvider.object)
|
||||
.then(() => {
|
||||
// Then:
|
||||
// ... Account store should have been called to get dehydrated accounts
|
||||
mocks.mockAccountStore.verify(x => x.getAccountsByProvider(TypeMoq.It.isValue(noAccountProvider.id)), TypeMoq.Times.once());
|
||||
|
||||
// ... The provider should have been initialized
|
||||
mockProvider.verify(x => x.initialize(TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||
|
||||
// ... The provider added event should have fired
|
||||
mocks.eventVerifierProviderAdded.assertFiredWithVerify((param: AccountProviderAddedEventParams) => {
|
||||
assert.equal(param.addedProvider, noAccountProvider);
|
||||
assert.ok(Array.isArray(param.initialAccounts));
|
||||
assert.equal(param.initialAccounts.length, 0);
|
||||
});
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
err => done(err)
|
||||
);
|
||||
});
|
||||
|
||||
test('Unregister provider - success', done => {
|
||||
// Setup:
|
||||
// ... Create ams
|
||||
let mocks = getTestState();
|
||||
|
||||
// ... Register a provider to remove
|
||||
let mockProvider = getMockAccountProvider();
|
||||
mocks.accountManagementService.registerProvider(noAccountProvider, mockProvider.object)
|
||||
.then((success) => {
|
||||
// If: I remove an account provider
|
||||
mocks.accountManagementService.unregisterProvider(noAccountProvider);
|
||||
|
||||
// Then: The provider removed event should have fired
|
||||
mocks.eventVerifierProviderRemoved.assertFired(noAccountProvider);
|
||||
}, error => {
|
||||
}).then(() => done(), err => done(err));
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
function getTestState(): AccountManagementState {
|
||||
// Create mock account store
|
||||
let mockAccountStore = TypeMoq.Mock.ofType<IAccountStore>(AccountStore);
|
||||
mockAccountStore.setup(x => x.getAccountsByProvider(TypeMoq.It.isValue(noAccountProvider.id)))
|
||||
.returns(() => Promise.resolve([]));
|
||||
mockAccountStore.setup(x => x.getAccountsByProvider(TypeMoq.It.isValue(hasAccountProvider.id)))
|
||||
.returns(() => Promise.resolve(accountList));
|
||||
|
||||
// Create instantiation service
|
||||
let mockInstantiationService = TypeMoq.Mock.ofType(InstantiationService, TypeMoq.MockBehavior.Strict);
|
||||
mockInstantiationService.setup(x => x.createInstance<AccountStore>(TypeMoq.It.isValue(AccountStore), TypeMoq.It.isAny()))
|
||||
.returns(() => mockAccountStore.object);
|
||||
|
||||
// Create mock memento
|
||||
let mockMemento = {};
|
||||
|
||||
// Create the account management service
|
||||
let ams = new AccountManagementService(mockMemento, mockInstantiationService.object, null, new SqlOAuthTestService());
|
||||
|
||||
// Wire up event handlers
|
||||
let evUpdate = new EventVerifierSingle<UpdateAccountListEventParams>();
|
||||
let evAddProvider = new EventVerifierSingle<AccountProviderAddedEventParams>();
|
||||
let evRemoveProvider = new EventVerifierSingle<data.AccountProviderMetadata>();
|
||||
ams.updateAccountListEvent(evUpdate.eventHandler);
|
||||
ams.addAccountProviderEvent(evAddProvider.eventHandler);
|
||||
ams.removeAccountProviderEvent(evRemoveProvider.eventHandler);
|
||||
|
||||
// Create the account management service
|
||||
return {
|
||||
accountManagementService: ams,
|
||||
instantiationService: mockInstantiationService,
|
||||
mockAccountStore: mockAccountStore,
|
||||
eventVerifierUpdate: evUpdate,
|
||||
eventVerifierProviderAdded: evAddProvider,
|
||||
eventVerifierProviderRemoved: evRemoveProvider
|
||||
};
|
||||
}
|
||||
|
||||
function getMockAccountProvider(): TypeMoq.Mock<data.AccountProvider> {
|
||||
let mockProvider = TypeMoq.Mock.ofType<data.AccountProvider>(AccountProviderStub);
|
||||
mockProvider.setup(x => x.clear(TypeMoq.It.isAny())).returns(() => Promise.resolve());
|
||||
mockProvider.setup(x => x.initialize(TypeMoq.It.isAny())).returns(param => Promise.resolve(param));
|
||||
mockProvider.setup(x => x.prompt()).returns(() => Promise.resolve(account));
|
||||
|
||||
return mockProvider;
|
||||
}
|
||||
|
||||
interface AccountManagementState {
|
||||
accountManagementService: AccountManagementService;
|
||||
instantiationService: TypeMoq.Mock<InstantiationService>;
|
||||
mockAccountStore: TypeMoq.Mock<IAccountStore>;
|
||||
eventVerifierUpdate: EventVerifierSingle<UpdateAccountListEventParams>;
|
||||
eventVerifierProviderAdded: EventVerifierSingle<AccountProviderAddedEventParams>;
|
||||
eventVerifierProviderRemoved: EventVerifierSingle<data.AccountProviderMetadata>;
|
||||
}
|
||||
442
src/sqltest/services/accountManagement/accountStore.test.ts
Normal file
442
src/sqltest/services/accountManagement/accountStore.test.ts
Normal file
@@ -0,0 +1,442 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as data from 'data';
|
||||
import AccountStore from 'sql/services/accountManagement/accountStore';
|
||||
import {EventVerifierSingle} from 'sqltest/utils/eventVerifier';
|
||||
|
||||
suite('Account Store Tests', () => {
|
||||
test('AddOrUpdate - Uninitialized memento', done => {
|
||||
// Setup: Create account store w/o initialized memento
|
||||
let memento = {};
|
||||
let as = new AccountStore(memento);
|
||||
|
||||
// If: I add an account to the store
|
||||
as.addOrUpdate(account1)
|
||||
.then(result => {
|
||||
// Then:
|
||||
// ... I should have gotten back a result indicating the account was added
|
||||
assert.ok(result.accountAdded);
|
||||
assert.ok(!result.accountModified);
|
||||
assertAccountEqual(result.changedAccount, account1);
|
||||
|
||||
// ... The memento should have been initialized and account added
|
||||
assert.ok(Array.isArray(memento[AccountStore.MEMENTO_KEY]));
|
||||
assert.equal(memento[AccountStore.MEMENTO_KEY].length, 1);
|
||||
assertAccountEqual(memento[AccountStore.MEMENTO_KEY][0], account1);
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
e => done(e)
|
||||
);
|
||||
});
|
||||
|
||||
test('AddOrUpdate - Adds to accounts', done => {
|
||||
// Setup: Create account store with initialized memento with accounts
|
||||
let memento = {};
|
||||
memento[AccountStore.MEMENTO_KEY] = [];
|
||||
let as = new AccountStore(memento);
|
||||
|
||||
// If: I add an account to the store
|
||||
as.addOrUpdate(account1)
|
||||
.then(result => {
|
||||
// Then:
|
||||
// ... I should have gotten back a result indicating the account was added
|
||||
assert.ok(result.accountAdded);
|
||||
assert.ok(!result.accountModified);
|
||||
assertAccountEqual(result.changedAccount, account1);
|
||||
|
||||
// ... The memento should have the account added
|
||||
assert.ok(Array.isArray(memento[AccountStore.MEMENTO_KEY]));
|
||||
assert.equal(memento[AccountStore.MEMENTO_KEY].length, 1);
|
||||
assertAccountEqual(memento[AccountStore.MEMENTO_KEY][0], account1);
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
e => done(e)
|
||||
);
|
||||
});
|
||||
|
||||
test('AddOrUpdate - Updates account', done => {
|
||||
// Setup: Create account store with initialized memento with accounts
|
||||
let memento = getTestMemento();
|
||||
let as = new AccountStore(memento);
|
||||
|
||||
// If: I add an account to the store that already exists
|
||||
let param = <data.Account>{
|
||||
key: account2.key,
|
||||
displayInfo: account1.displayInfo,
|
||||
isStale: account1.isStale
|
||||
};
|
||||
as.addOrUpdate(param)
|
||||
.then(result => {
|
||||
// Then:
|
||||
// ... I should have gotten back a result indicating the account was updated
|
||||
assert.ok(result.accountModified);
|
||||
assert.ok(!result.accountAdded);
|
||||
assertAccountEqual(result.changedAccount, param);
|
||||
|
||||
// ... The memento should have been initialized and account updated
|
||||
assert.ok(Array.isArray(memento[AccountStore.MEMENTO_KEY]));
|
||||
assert.equal(memento[AccountStore.MEMENTO_KEY].length, 2);
|
||||
assertAccountEqual(memento[AccountStore.MEMENTO_KEY][0], account1);
|
||||
assertAccountEqual(memento[AccountStore.MEMENTO_KEY][1], param);
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
e => done(e)
|
||||
);
|
||||
});
|
||||
|
||||
test('GetAccountsByProvider - Uninitialized memento', done => {
|
||||
// Setup: Create account store w/o initialized memento
|
||||
let memento = {};
|
||||
let as = new AccountStore(memento);
|
||||
|
||||
// If: I get accounts by provider
|
||||
as.getAccountsByProvider('azure')
|
||||
.then(result => {
|
||||
// Then:
|
||||
// ... I should get back an empty array
|
||||
assert.ok(Array.isArray(result));
|
||||
assert.equal(result.length, 0);
|
||||
|
||||
// ... Memento should not have been written
|
||||
assert.equal(Object.keys(memento).length, 0);
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
e => done(e)
|
||||
);
|
||||
});
|
||||
|
||||
test('GetAccountsByProvider - No accounts', done => {
|
||||
// Setup: Create account store with initialized memento with accounts
|
||||
let memento = {};
|
||||
memento[AccountStore.MEMENTO_KEY] = [];
|
||||
let as = new AccountStore(memento);
|
||||
|
||||
// If: I get accounts when there aren't any accounts
|
||||
as.getAccountsByProvider('azure')
|
||||
.then(result => {
|
||||
// Then: I should get back an empty array
|
||||
assert.ok(Array.isArray(result));
|
||||
assert.equal(result.length, 0);
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
e => done(e)
|
||||
);
|
||||
});
|
||||
|
||||
test('GetAccountsByProvider - Accounts, but no accounts for provider', done => {
|
||||
// Setup: Create account store with initialized memento with accounts
|
||||
let memento = getTestMemento();
|
||||
let as = new AccountStore(memento);
|
||||
|
||||
// If: I get accounts by provider that doesn't have accounts
|
||||
as.getAccountsByProvider('cloudycloud')
|
||||
.then(result => {
|
||||
// Then: I should get back an empty array
|
||||
assert.ok(Array.isArray(result));
|
||||
assert.equal(result.length, 0);
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
e => done(e)
|
||||
);
|
||||
});
|
||||
|
||||
test('GetAccountsByProvider - Accounts for provider', done => {
|
||||
// Setup: Create account store with initialized memento with accounts
|
||||
let memento = getTestMemento();
|
||||
let as = new AccountStore(memento);
|
||||
|
||||
// If: I get accounts by provider that has accounts
|
||||
as.getAccountsByProvider('azure')
|
||||
.then(result => {
|
||||
// Then: I should get the accounts
|
||||
assert.ok(Array.isArray(result));
|
||||
assert.equal(result.length, 2);
|
||||
assertAccountEqual(result[0], memento[AccountStore.MEMENTO_KEY][0]);
|
||||
assertAccountEqual(result[1], memento[AccountStore.MEMENTO_KEY][1]);
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
e => done(e)
|
||||
);
|
||||
});
|
||||
|
||||
test('GetAllAccounts - Uninitialized memento', done => {
|
||||
// Setup: Create account store w/o initialized memento
|
||||
let memento = {};
|
||||
let as = new AccountStore(memento);
|
||||
|
||||
// If: I get accounts
|
||||
as.getAllAccounts()
|
||||
.then(result => {
|
||||
// Then:
|
||||
// ... I should get back an empty array
|
||||
assert.ok(Array.isArray(result));
|
||||
assert.equal(result.length, 0);
|
||||
|
||||
// ... Memento should not have been written
|
||||
assert.equal(Object.keys(memento).length, 0);
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
e => done(e)
|
||||
);
|
||||
});
|
||||
|
||||
test('GetAllAccounts - No accounts', done => {
|
||||
// Setup: Create account store with initialized memento with accounts
|
||||
let memento = {};
|
||||
memento[AccountStore.MEMENTO_KEY] = [];
|
||||
let as = new AccountStore(memento);
|
||||
|
||||
// If: I get accounts when there aren't any accounts
|
||||
as.getAllAccounts()
|
||||
.then(result => {
|
||||
// Then: I should get back an empty array
|
||||
assert.ok(Array.isArray(result));
|
||||
assert.equal(result.length, 0);
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
e => done(e)
|
||||
);
|
||||
});
|
||||
|
||||
test('GetAllAccounts - Accounts', done => {
|
||||
// Setup: Create account store with initialized memento with accounts
|
||||
let memento = getTestMemento();
|
||||
let as = new AccountStore(memento);
|
||||
|
||||
// If: I get accounts
|
||||
as.getAllAccounts()
|
||||
.then(result => {
|
||||
// Then: I should get the accounts
|
||||
assert.ok(Array.isArray(result));
|
||||
assert.equal(result.length, 2);
|
||||
assertAccountEqual(result[0], memento[AccountStore.MEMENTO_KEY][0]);
|
||||
assertAccountEqual(result[1], memento[AccountStore.MEMENTO_KEY][1]);
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
e => done(e)
|
||||
);
|
||||
});
|
||||
|
||||
test('Remove - Uninitialized menento', done => {
|
||||
// Setup: Create account store w/o initialized memento
|
||||
let memento = {};
|
||||
let as = new AccountStore(memento);
|
||||
|
||||
// If: I remove an account when there's an uninitialized memento
|
||||
as.remove(account1.key)
|
||||
.then(result => {
|
||||
// Then:
|
||||
// ... I should get back false (no account removed)
|
||||
assert.ok(!result);
|
||||
|
||||
// ... The memento should have been initialized
|
||||
assert.ok(Array.isArray(memento[AccountStore.MEMENTO_KEY]));
|
||||
assert.equal(memento[AccountStore.MEMENTO_KEY].length, 0);
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
e => done(e)
|
||||
);
|
||||
});
|
||||
|
||||
test('Remove - Account does not exist', done => {
|
||||
// Setup: Create account store with initialized memento with accounts
|
||||
let memento = {};
|
||||
memento[AccountStore.MEMENTO_KEY] = [];
|
||||
let as = new AccountStore(memento);
|
||||
|
||||
// If: I remove an account that doesn't exist
|
||||
as.remove({providerId: 'cloudyCloud', accountId: 'testyTest'})
|
||||
.then(result => {
|
||||
// Then:
|
||||
// ... I should get back false (no account removed)
|
||||
assert.ok(!result);
|
||||
|
||||
// ... The memento should still be empty
|
||||
assert.ok(Array.isArray(memento[AccountStore.MEMENTO_KEY]));
|
||||
assert.equal(memento[AccountStore.MEMENTO_KEY].length, 0);
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
e => done(e)
|
||||
);
|
||||
});
|
||||
|
||||
test('Remove - Account exists', done => {
|
||||
// Setup: Create account store with initialized memento with accounts
|
||||
let memento = getTestMemento();
|
||||
let as = new AccountStore(memento);
|
||||
|
||||
// If: I remove an account that does exist
|
||||
as.remove(account1.key)
|
||||
.then(result => {
|
||||
// Then:
|
||||
// ... I should get back true (account removed)
|
||||
assert.ok(result);
|
||||
|
||||
// ... The memento should have removed the first account
|
||||
assert.ok(Array.isArray(memento[AccountStore.MEMENTO_KEY]));
|
||||
assert.equal(memento[AccountStore.MEMENTO_KEY].length, 1);
|
||||
assertAccountEqual(memento[AccountStore.MEMENTO_KEY][0], account2);
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
e => done(e)
|
||||
);
|
||||
});
|
||||
|
||||
test('Update - Uninitialized menento', done => {
|
||||
// Setup:
|
||||
// ... Create account store w/o initialized memento
|
||||
let memento = {};
|
||||
let as = new AccountStore(memento);
|
||||
|
||||
// ... Create a callback that we can verify was called
|
||||
let updateCallback = new EventVerifierSingle<data.Account>();
|
||||
|
||||
// If: I update an account
|
||||
as.update(account1.key, updateCallback.eventHandler)
|
||||
.then(result => {
|
||||
// Then:
|
||||
// ... I should get back false (account did not change)
|
||||
assert.ok(!result);
|
||||
|
||||
// ... The memento should have been initialized
|
||||
assert.ok(Array.isArray(memento[AccountStore.MEMENTO_KEY]));
|
||||
assert.equal(memento[AccountStore.MEMENTO_KEY].length, 0);
|
||||
|
||||
// ... The callback shouldn't have been called
|
||||
updateCallback.assertNotFired();
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
e => done(e)
|
||||
);
|
||||
});
|
||||
|
||||
test('Update - Account does not exist', done => {
|
||||
// Setup: Create account store with initialized memento with accounts
|
||||
let memento = {};
|
||||
memento[AccountStore.MEMENTO_KEY] = [];
|
||||
let as = new AccountStore(memento);
|
||||
|
||||
// ... Create a callback that we can verify was called
|
||||
let updateCallback = new EventVerifierSingle<data.Account>();
|
||||
|
||||
// If: I update an account that doesn't exist
|
||||
as.update({accountId: 'testyTest', providerId: 'cloudyCloud'}, updateCallback.eventHandler)
|
||||
.then(result => {
|
||||
// Then:
|
||||
// ... I should get back false (account did not change)
|
||||
assert.ok(!result);
|
||||
|
||||
// ... The memento should still be empty
|
||||
assert.ok(Array.isArray(memento[AccountStore.MEMENTO_KEY]));
|
||||
assert.equal(memento[AccountStore.MEMENTO_KEY].length, 0);
|
||||
|
||||
// ... The callback shouldn't have been called
|
||||
updateCallback.assertNotFired();
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
e => done(e)
|
||||
);
|
||||
});
|
||||
|
||||
test('Update - Account exists', done => {
|
||||
// Setup: Create account store with initialized memento with accounts
|
||||
let memento = getTestMemento();
|
||||
let as = new AccountStore(memento);
|
||||
|
||||
// ... Create a callback to update the account
|
||||
let newDisplayName = 'Display Name Changed!';
|
||||
let updateCallback = (arg: data.Account) => {
|
||||
arg.displayInfo.displayName = newDisplayName;
|
||||
};
|
||||
|
||||
// If: I update an account that exists
|
||||
as.update(account1.key, updateCallback)
|
||||
.then(result => {
|
||||
// Then:
|
||||
// ... I should get back true (account did change)
|
||||
assert.ok(result);
|
||||
|
||||
// ... The memento still contains two accounts
|
||||
assert.ok(Array.isArray(memento[AccountStore.MEMENTO_KEY]));
|
||||
assert.equal(memento[AccountStore.MEMENTO_KEY].length, 2);
|
||||
|
||||
// ... Account 1 should have been updated
|
||||
assert.equal(memento[AccountStore.MEMENTO_KEY][0].displayInfo.displayName, newDisplayName);
|
||||
|
||||
// ... Account 2 should have stayed the same
|
||||
assertAccountEqual(memento[AccountStore.MEMENTO_KEY][1], account2);
|
||||
})
|
||||
.then(
|
||||
() => done(),
|
||||
e => done(e)
|
||||
);
|
||||
});
|
||||
|
||||
// TODO: Test to make sure operations occur sequentially
|
||||
});
|
||||
|
||||
// TODO: Reinstate contextual logo once UI changes are checked in
|
||||
const account1 = <data.Account>{
|
||||
key: {
|
||||
providerId: 'azure',
|
||||
accountId: 'testAccount1'
|
||||
},
|
||||
displayInfo: {
|
||||
displayName: 'Test Account 1',
|
||||
//contextualLogo: {light: '', dark: ''},
|
||||
contextualDisplayName: 'Azure Account'
|
||||
},
|
||||
isStale: false
|
||||
};
|
||||
|
||||
const account2 = <data.Account>{
|
||||
key: {
|
||||
providerId: 'azure',
|
||||
accountId: 'testAccount2'
|
||||
},
|
||||
displayInfo: {
|
||||
displayName: 'Test Account 2',
|
||||
//contextualLogo: {light: '', dark: ''},
|
||||
contextualDisplayName: 'Azure Account'
|
||||
},
|
||||
isStale: false
|
||||
};
|
||||
|
||||
function getTestMemento() {
|
||||
let memento = {};
|
||||
memento[AccountStore.MEMENTO_KEY] = [account1, account2];
|
||||
|
||||
return memento;
|
||||
}
|
||||
|
||||
function assertAccountEqual(a: data.Account, b: data.Account) {
|
||||
assert.equal(a.key.providerId, b.key.providerId);
|
||||
assert.equal(a.key.accountId, b.key.accountId);
|
||||
|
||||
assert.equal(a.displayInfo.contextualDisplayName, b.displayInfo.contextualDisplayName);
|
||||
//assert.equal(a.displayInfo.contextualLogo, b.displayInfo.contextualLogo);
|
||||
assert.equal(a.displayInfo.displayName, b.displayInfo.displayName);
|
||||
|
||||
assert.equal(a.isStale, b.isStale);
|
||||
}
|
||||
82
src/sqltest/stubs/accountManagementStubs.ts
Normal file
82
src/sqltest/stubs/accountManagementStubs.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as data from 'data';
|
||||
import Event from 'vs/base/common/event';
|
||||
import { IAccountManagementService } from 'sql/services/accountManagement/interfaces';
|
||||
import { AccountProviderAddedEventParams, UpdateAccountListEventParams } from 'sql/services/accountManagement/eventTypes';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
|
||||
export class AccountManagementTestService implements IAccountManagementService {
|
||||
_serviceBrand: any;
|
||||
|
||||
public get addAccountProviderEvent(): Event<AccountProviderAddedEventParams> {return () => {return undefined;};}
|
||||
public get removeAccountProviderEvent(): Event<data.AccountProviderMetadata> {return () => {return undefined;};}
|
||||
public get updateAccountListEvent(): Event<UpdateAccountListEventParams> {return () => {return undefined;};}
|
||||
|
||||
addAccount(providerId: string): Thenable<data.Account> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getAccountProviderMetadata(): Thenable<data.AccountProviderMetadata[]> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getAccountsForProvider(providerId: string): Thenable<data.Account[]> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getSecurityToken(account: data.Account): Thenable<{}> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
removeAccount(accountKey: data.AccountKey): Thenable<boolean> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
openAccountListDialog(): TPromise<any> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
performOAuthAuthorization(url: string, silent: boolean): Thenable<string> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
registerProvider(providerMetadata: data.AccountProviderMetadata, provider: data.AccountProvider): void {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
shutdown(): void {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
unregisterProvider(providerMetadata: data.AccountProviderMetadata): void {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export class AccountProviderStub implements data.AccountProvider {
|
||||
clear(account: data.AccountKey): Thenable<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
getSecurityToken(account: data.Account): Thenable<{}> {
|
||||
return Promise.resolve({});
|
||||
}
|
||||
|
||||
initialize(storedAccounts: data.Account[]): Thenable<data.Account[]> {
|
||||
return Promise.resolve(storedAccounts);
|
||||
}
|
||||
|
||||
prompt(): Thenable<data.Account> {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
refresh(account: data.Account): Thenable<data.Account> {
|
||||
return Promise.resolve(account);
|
||||
}
|
||||
}
|
||||
128
src/sqltest/stubs/capabilitiesTestService.ts
Normal file
128
src/sqltest/stubs/capabilitiesTestService.ts
Normal file
@@ -0,0 +1,128 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
import data = require('data');
|
||||
import { ConnectionManagementInfo } from 'sql/parts/connection/common/connectionManagementInfo';
|
||||
import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
|
||||
import Event from 'vs/base/common/event';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
|
||||
|
||||
export class CapabilitiesTestService implements ICapabilitiesService {
|
||||
|
||||
public _serviceBrand: any;
|
||||
|
||||
private _providers: data.CapabilitiesProvider[] = [];
|
||||
|
||||
private _capabilities: data.DataProtocolServerCapabilities[] = [];
|
||||
|
||||
|
||||
constructor() {
|
||||
|
||||
let connectionProvider: data.ConnectionProviderOptions = {
|
||||
options: [
|
||||
{
|
||||
name: 'serverName',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 0,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'databaseName',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 1,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'userName',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 3,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'authenticationType',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 2,
|
||||
valueType: 0
|
||||
},
|
||||
{
|
||||
name: 'password',
|
||||
displayName: undefined,
|
||||
description: undefined,
|
||||
groupName: undefined,
|
||||
categoryValues: undefined,
|
||||
defaultValue: undefined,
|
||||
isIdentity: true,
|
||||
isRequired: true,
|
||||
specialValueType: 4,
|
||||
valueType: 0
|
||||
}
|
||||
]
|
||||
};
|
||||
let msSQLCapabilities = {
|
||||
protocolVersion: '1',
|
||||
providerName: 'MSSQL',
|
||||
providerDisplayName: 'MSSQL',
|
||||
connectionProvider: connectionProvider,
|
||||
adminServicesProvider: undefined,
|
||||
features: undefined
|
||||
};
|
||||
this._capabilities.push(msSQLCapabilities);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a list of registered server capabilities
|
||||
*/
|
||||
public getCapabilities(): data.DataProtocolServerCapabilities[] {
|
||||
return this._capabilities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the capabilities provider and query the provider for its capabilities
|
||||
* @param provider
|
||||
*/
|
||||
public registerProvider(provider: data.CapabilitiesProvider): void {
|
||||
}
|
||||
|
||||
// Event Emitters
|
||||
public get onProviderRegisteredEvent(): Event<data.DataProtocolServerCapabilities> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public isFeatureAvailable(featureName: Action, connectionManagementInfo: ConnectionManagementInfo): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
public onCapabilitiesReady(): Promise<void> {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
}
|
||||
|
||||
22
src/sqltest/stubs/connectionDialogTestService.ts
Normal file
22
src/sqltest/stubs/connectionDialogTestService.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import {
|
||||
IConnectionDialogService, IConnectionManagementService, INewConnectionParams
|
||||
} from 'sql/parts/connection/common/connectionManagement';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
||||
|
||||
export class ConnectionDialogTestService implements IConnectionDialogService {
|
||||
_serviceBrand: any;
|
||||
|
||||
public showDialog(connectionManagementService: IConnectionManagementService,
|
||||
params: INewConnectionParams, model: IConnectionProfile, error?: string): TPromise<void> {
|
||||
let none: void;
|
||||
return TPromise.as(none);
|
||||
}
|
||||
|
||||
}
|
||||
236
src/sqltest/stubs/connectionManagementService.test.ts
Normal file
236
src/sqltest/stubs/connectionManagementService.test.ts
Normal file
@@ -0,0 +1,236 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IConnectionManagementService, IConnectableInput, IConnectionCompletionOptions, IConnectionCallbacks, IConnectionResult, INewConnectionParams }
|
||||
from 'sql/parts/connection/common/connectionManagement';
|
||||
import { IConnectionProfileGroup, ConnectionProfileGroup } from 'sql/parts/connection/common/connectionProfileGroup';
|
||||
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
||||
import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
|
||||
import { ConnectionManagementInfo } from 'sql/parts/connection/common/connectionManagementInfo';
|
||||
import data = require('data');
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
|
||||
// Test stubs for commonly used objects
|
||||
|
||||
export class TestConnectionManagementService implements IConnectionManagementService {
|
||||
_serviceBrand: any;
|
||||
onAddConnectionProfile = undefined;
|
||||
onDeleteConnectionProfile = undefined;
|
||||
onConnectionChanged = undefined;
|
||||
onLanguageFlavorChanged = undefined;
|
||||
|
||||
public get onConnect(): Event<any> {
|
||||
let conEvent = new Emitter<any>();
|
||||
return conEvent.event;
|
||||
}
|
||||
|
||||
public get onDisconnect(): Event<any> {
|
||||
let conEvent = new Emitter<any>();
|
||||
return conEvent.event;
|
||||
}
|
||||
|
||||
registerProvider(providerId: string, provider: data.ConnectionProvider): void {
|
||||
|
||||
}
|
||||
|
||||
showConnectionDialog(params?: INewConnectionParams, model?: IConnectionProfile, error?: string): Promise<void> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
showCreateServerGroupDialog(): Promise<void> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
showEditServerGroupDialog(group: ConnectionProfileGroup): Promise<void> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
onConnectionComplete(handle: number, connectionInfoSummary: data.ConnectionInfoSummary): void {
|
||||
|
||||
}
|
||||
|
||||
onIntelliSenseCacheComplete(handle: number, connectionUri: string): void {
|
||||
|
||||
}
|
||||
|
||||
public onConnectionChangedNotification(handle: number, changedConnInfo: data.ChangedConnectionInfo): void {
|
||||
|
||||
}
|
||||
|
||||
getCurrentConnectionSummary(): data.ConnectionSummary {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getConnectionGroups(): ConnectionProfileGroup[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
getActiveConnections(): ConnectionProfile[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
saveProfileGroup(profile: IConnectionProfileGroup): Promise<string> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getRecentConnections(): ConnectionProfile[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
public clearRecentConnectionsList(): void {
|
||||
return;
|
||||
}
|
||||
|
||||
getUnsavedConnections(): ConnectionProfile[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
changeGroupIdForConnectionGroup(source: IConnectionProfileGroup, target: IConnectionProfileGroup): Promise<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
changeGroupIdForConnection(source: ConnectionProfile, targetGroupId: string): Promise<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
deleteConnection(connection: ConnectionProfile): Promise<boolean> {
|
||||
return new Promise<boolean>((resolve, reject) => {
|
||||
resolve(true);
|
||||
});
|
||||
}
|
||||
|
||||
deleteConnectionGroup(group: ConnectionProfileGroup): Promise<boolean> {
|
||||
return new Promise<boolean>((resolve, reject) => {
|
||||
resolve(true);
|
||||
});
|
||||
}
|
||||
|
||||
getAdvancedProperties(): data.ConnectionOption[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
getConnectionId(connectionProfile: ConnectionProfile): string {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getFormattedUri(uri: string, connectionProfile: ConnectionProfile): string {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
isConnected(fileUri: string, connectionProfile?: ConnectionProfile): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
isRecent(connectionProfile: ConnectionProfile): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
isProfileConnected(connectionProfile: IConnectionProfile): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
isProfileConnecting(connectionProfile: IConnectionProfile): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
findExistingConnection(connection: IConnectionProfile, purpose?: 'dashboard' | 'insights' | 'connection'): ConnectionProfile {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
connect(connection: IConnectionProfile, uri: string, options?: IConnectionCompletionOptions, callbacks?: IConnectionCallbacks): Promise<IConnectionResult> {
|
||||
return new Promise<IConnectionResult>((resolve, reject) => {
|
||||
resolve({ connected: true, errorMessage: undefined, errorCode: undefined });
|
||||
});
|
||||
}
|
||||
|
||||
connectAndSaveProfile(connection: IConnectionProfile, uri: string, options?: IConnectionCompletionOptions, callbacks?: IConnectionCallbacks): Promise<IConnectionResult> {
|
||||
return new Promise<IConnectionResult>(() => true);
|
||||
}
|
||||
|
||||
disconnectEditor(owner: IConnectableInput): Promise<boolean> {
|
||||
return new Promise<boolean>(() => true);
|
||||
}
|
||||
|
||||
disconnect(connection: IConnectionProfile);
|
||||
disconnect(uri: string);
|
||||
disconnect(input: any): Promise<boolean> {
|
||||
return new Promise<boolean>((resolve, reject) => {
|
||||
resolve(true);
|
||||
});
|
||||
}
|
||||
|
||||
getConnectionProfile(fileUri: string): IConnectionProfile {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getConnectionInfo(fileUri: string): ConnectionManagementInfo {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
addSavedPassword(connectionProfile: IConnectionProfile): Promise<IConnectionProfile> {
|
||||
return new Promise<IConnectionProfile>(() => connectionProfile);
|
||||
}
|
||||
|
||||
public listDatabases(connectionUri: string): Thenable<data.ListDatabasesResult> {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
cancelConnection(connection: IConnectionProfile): Thenable<boolean> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
cancelEditorConnection(owner: IConnectableInput): Thenable<boolean> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
showDashboard(connection: ConnectionProfile): Promise<boolean> {
|
||||
return new Promise(() => true);
|
||||
}
|
||||
|
||||
closeDashboard(uri: string): void {
|
||||
}
|
||||
|
||||
changeDatabase(connectionUri: string, databaseName: string): Thenable<boolean> {
|
||||
return new Promise(() => true);
|
||||
}
|
||||
|
||||
editGroup(group: ConnectionProfileGroup): Promise<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
getProviderIdFromUri(ownerUri: string): string {
|
||||
return undefined;
|
||||
}
|
||||
hasRegisteredServers(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
getCapabilities(providerName: string): data.DataProtocolServerCapabilities {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
canChangeConnectionConfig(profile: ConnectionProfile, newGroupID: string): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
doChangeLanguageFlavor(uri: string, language: string, flavor: string): void {
|
||||
|
||||
}
|
||||
ensureDefaultLanguageFlavor(uri: string): void {
|
||||
|
||||
}
|
||||
|
||||
public getProviderNames(): string[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
connectIfNotConnected(connection: IConnectionProfile, purpose?: 'dashboard' | 'insights' | 'connection'): Promise<string> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
rebuildIntelliSenseCache(uri: string): Thenable<void> {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
46
src/sqltest/stubs/connectionProviderStub.ts
Normal file
46
src/sqltest/stubs/connectionProviderStub.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import data = require('data');
|
||||
|
||||
export class ConnectionProviderStub implements data.ConnectionProvider {
|
||||
handle: number = 1;
|
||||
|
||||
connect(connectionUri: string, connectionInfo: data.ConnectionInfo): Thenable<boolean> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
disconnect(connectionUri: string): Thenable<boolean> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
cancelConnect(connectionUri: string): Thenable<boolean> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
listDatabases(connectionUri: string): Thenable<data.ListDatabasesResult> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
changeDatabase(connectionUri: string, newDatabase: string): Thenable<boolean> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
rebuildIntelliSenseCache(connectionUri: string): Thenable<void> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
registerOnConnectionComplete(handler: (connSummary: data.ConnectionInfoSummary) => any) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
registerOnIntelliSenseCacheComplete(handler: (connectionUri: string) => any) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
registerOnConnectionChanged(handler: (changedConnInfo: data.ChangedConnectionInfo) => any) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
38
src/sqltest/stubs/contextKeyServiceStub.ts
Normal file
38
src/sqltest/stubs/contextKeyServiceStub.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IContextKeyService, IContextKeyServiceTarget, IContextKey, ContextKeyExpr, IContext } from 'vs/platform/contextkey/common/contextkey';
|
||||
import Event from 'vs/base/common/event';
|
||||
|
||||
export class ContextKeyServiceStub implements IContextKeyService {
|
||||
_serviceBrand: any;
|
||||
|
||||
dispose(): void {
|
||||
//
|
||||
}
|
||||
|
||||
onDidChangeContext: Event<string[]>;
|
||||
|
||||
createKey<T>(key: string, defaultValue: T): IContextKey<T> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
contextMatchesRules(rules: ContextKeyExpr): boolean {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getContextKeyValue<T>(key: string): T {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
createScoped(target?: IContextKeyServiceTarget): IContextKeyService {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getContext(target: IContextKeyServiceTarget): IContext {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
}
|
||||
56
src/sqltest/stubs/credentialsTestStubs.ts
Normal file
56
src/sqltest/stubs/credentialsTestStubs.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as data from 'data';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import {CredentialManagementEvents, ICredentialsService} from "sql/services/credentials/credentialsService";
|
||||
import {IDisposable} from "vs/base/common/lifecycle";
|
||||
|
||||
export class CredentialsTestProvider implements data.CredentialProvider {
|
||||
handle: number;
|
||||
|
||||
public storedCredentials: {[K: string]: data.Credential} = {};
|
||||
|
||||
saveCredential(credentialId: string, password: string): Thenable<boolean> {
|
||||
this.storedCredentials[credentialId] = {
|
||||
credentialId: credentialId,
|
||||
password: password
|
||||
};
|
||||
return TPromise.as(true);
|
||||
}
|
||||
|
||||
readCredential(credentialId: string): Thenable<data.Credential> {
|
||||
return TPromise.as(this.storedCredentials[credentialId]);
|
||||
}
|
||||
|
||||
deleteCredential(credentialId: string): Thenable<boolean> {
|
||||
let exists = this.storedCredentials[credentialId] !== undefined;
|
||||
delete this.storedCredentials[credentialId];
|
||||
return TPromise.as(exists);
|
||||
}
|
||||
}
|
||||
|
||||
export class CredentialsTestService implements ICredentialsService {
|
||||
_serviceBrand: any;
|
||||
|
||||
saveCredential(credentialId: string, password: string): Thenable<boolean> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
readCredential(credentialId: string): Thenable<data.Credential> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
deleteCredential(credentialId: string): Thenable<boolean> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
addEventListener(handle: number, events: CredentialManagementEvents): IDisposable {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
}
|
||||
134
src/sqltest/stubs/editorGroupService.ts
Normal file
134
src/sqltest/stubs/editorGroupService.ts
Normal file
@@ -0,0 +1,134 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { Position, IEditorInput } from 'vs/platform/editor/common/editor';
|
||||
import { IEditorStacksModel, IEditorGroup, EditorInput } from 'vs/workbench/common/editor';
|
||||
import Event from 'vs/base/common/event';
|
||||
import { ITabOptions, GroupArrangement, GroupOrientation } from 'vs/workbench/services/group/common/groupService';
|
||||
import { IEditorGroupService, IMoveOptions } from 'vs/workbench/services/group/common/groupService';
|
||||
import { EditorGroup } from "vs/workbench/common/editor/editorStacksModel";
|
||||
|
||||
export class EditorGroupTestService implements IEditorGroupService {
|
||||
_serviceBrand: ServiceIdentifier<any>;
|
||||
|
||||
/**
|
||||
* Emitted when editors or inputs change. Examples: opening, closing of editors. Active editor change.
|
||||
*/
|
||||
onEditorsChanged: Event<void>;
|
||||
|
||||
/**
|
||||
* Emitted when opening an editor fails.
|
||||
*/
|
||||
onEditorOpenFail: Event<IEditorInput>;
|
||||
|
||||
/**
|
||||
* Emitted when a editors are moved to another position.
|
||||
*/
|
||||
onEditorsMoved: Event<void>;
|
||||
|
||||
/**
|
||||
* Emitted when the editor group orientation was changed.
|
||||
*/
|
||||
onGroupOrientationChanged: Event<void>;
|
||||
|
||||
/**
|
||||
* Emitted when tab options changed.
|
||||
*/
|
||||
onTabOptionsChanged: Event<ITabOptions>;
|
||||
|
||||
/**
|
||||
* Keyboard focus the editor group at the provided position.
|
||||
*/
|
||||
public focusGroup(group: EditorGroup): void;
|
||||
public focusGroup(position: Position): void;
|
||||
public focusGroup(arg1: any) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate the editor group at the provided position without moving focus.
|
||||
*/
|
||||
public activateGroup(group: EditorGroup): void;
|
||||
public activateGroup(position: Position): void;
|
||||
public activateGroup(arg1: any): void {
|
||||
}
|
||||
/**
|
||||
* Allows to move the editor group from one position to another.
|
||||
*/
|
||||
|
||||
|
||||
public moveGroup(from: EditorGroup, to: EditorGroup): void;
|
||||
public moveGroup(from: Position, to: Position): void;
|
||||
public moveGroup(arg1: any, arg2: any): void {
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to arrange editor groups according to the GroupArrangement enumeration.
|
||||
*/
|
||||
arrangeGroups(arrangement: GroupArrangement): void {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the editor group layout between vertical and horizontal orientation. Only applies
|
||||
* if more than one editor is opened.
|
||||
*/
|
||||
setGroupOrientation(orientation: GroupOrientation): void {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current editor group layout.
|
||||
*/
|
||||
getGroupOrientation(): GroupOrientation {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves an editor from one group to another. The index in the group is optional.
|
||||
*/
|
||||
moveEditor(input: IEditorInput, from: IEditorGroup, to: IEditorGroup, moveOptions?: IMoveOptions): void;
|
||||
moveEditor(input: IEditorInput, from: Position, to: Position, moveOptions?: IMoveOptions): void;
|
||||
moveEditor(input: EditorInput, arg2: any, arg3: any, index?: IMoveOptions): void {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides access to the editor stacks model
|
||||
*/
|
||||
getStacksModel(): IEditorStacksModel {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if tabs are shown, false otherwise.
|
||||
*/
|
||||
getTabOptions(): ITabOptions {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public pinEditor(group: EditorGroup, input: EditorInput): void;
|
||||
public pinEditor(position: Position, input: EditorInput): void;
|
||||
public pinEditor(arg1: any, input: EditorInput): void {
|
||||
|
||||
}
|
||||
|
||||
public unpinEditor(group: EditorGroup, input: EditorInput): void;
|
||||
public unpinEditor(position: Position, input: EditorInput): void;
|
||||
public unpinEditor(arg1: any, input: EditorInput): void {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize visible editor groups
|
||||
*/
|
||||
public resizeGroup(position: Position, groupSizeChange: number): void {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
14
src/sqltest/stubs/errorMessageServiceStub.ts
Normal file
14
src/sqltest/stubs/errorMessageServiceStub.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
import { IErrorMessageService } from 'sql/parts/connection/common/connectionManagement';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
|
||||
export class ErrorMessageServiceStub implements IErrorMessageService {
|
||||
_serviceBrand: any;
|
||||
showDialog(severity: Severity, headerTitle: string, message: string): void {
|
||||
}
|
||||
}
|
||||
30
src/sqltest/stubs/messageServiceStub.ts
Normal file
30
src/sqltest/stubs/messageServiceStub.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { IConfirmation, IMessageService, IMessageWithAction } from 'vs/platform/message/common/message';
|
||||
|
||||
export class MessageServiceStub implements IMessageService{
|
||||
_serviceBrand: any;
|
||||
|
||||
show(sev: Severity, message: string): () => void;
|
||||
show(sev: Severity, message: Error): () => void;
|
||||
show(sev: Severity, message: string[]): () => void;
|
||||
show(sev: Severity, message: Error[]): () => void;
|
||||
show(sev: Severity, message: IMessageWithAction): () => void;
|
||||
show(sev: Severity, message): () => void {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
hideAll(): void {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
confirm(confirmation: IConfirmation): boolean {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
34
src/sqltest/stubs/objectExplorerProviderTestService.ts
Normal file
34
src/sqltest/stubs/objectExplorerProviderTestService.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import data = require('data');
|
||||
|
||||
// Test stubs for commonly used objects
|
||||
|
||||
export class ObjectExplorerProviderTestService implements data.ObjectExplorerProvider {
|
||||
|
||||
public createNewSession(connInfo: data.ConnectionInfo): Thenable<data.ObjectExplorerCloseSessionResponse> {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
public expandNode(nodeInfo: data.ExpandNodeInfo): Thenable<boolean> {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
public refreshNode(nodeInfo: data.ExpandNodeInfo): Thenable<boolean> {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
public closeSession(closeSessionInfo: data.ObjectExplorerCloseSessionInfo): Thenable<data.ObjectExplorerCloseSessionResponse> {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
public registerOnSessionCreated(handler: (response: data.ObjectExplorerSession) => any): void {
|
||||
|
||||
}
|
||||
|
||||
public registerOnExpandCompleted(handler: (response: data.ObjectExplorerExpandInfo) => any): void {
|
||||
|
||||
}
|
||||
}
|
||||
18
src/sqltest/stubs/sqlOauthServiceStub.ts
Normal file
18
src/sqltest/stubs/sqlOauthServiceStub.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import { ISqlOAuthService } from 'sql/common/sqlOAuthService';
|
||||
|
||||
export class SqlOAuthTestService implements ISqlOAuthService {
|
||||
_serviceBrand: any;
|
||||
|
||||
performOAuthAuthorization(eventId: string, url: string, silent: boolean): void {
|
||||
}
|
||||
|
||||
registerOAuthCallback(handler: (event, args) => void): void {
|
||||
}
|
||||
}
|
||||
72
src/sqltest/stubs/storageTestService.ts
Normal file
72
src/sqltest/stubs/storageTestService.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
|
||||
export class StorageTestService implements IStorageService {
|
||||
_serviceBrand: any;
|
||||
|
||||
/**
|
||||
* Store a string value under the given key to local storage.
|
||||
*
|
||||
* The optional scope argument allows to define the scope of the operation.
|
||||
*/
|
||||
store(key: string, value: any, scope?: StorageScope): void {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Swap the value of a stored element to one of the two provided
|
||||
* values and use the defaultValue if no element with the given key
|
||||
* exists.
|
||||
*
|
||||
* The optional scope argument allows to define the scope of the operation.
|
||||
*/
|
||||
swap(key: string, valueA: any, valueB: any, scope?: StorageScope, defaultValue?: any): void {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an element stored under the provided key from local storage.
|
||||
*
|
||||
* The optional scope argument allows to define the scope of the operation.
|
||||
*/
|
||||
remove(key: string, scope?: StorageScope): void {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an element stored with the given key from local storage. Use
|
||||
* the provided defaultValue if the element is null or undefined.
|
||||
*
|
||||
* The optional scope argument allows to define the scope of the operation.
|
||||
*/
|
||||
get(key: string, scope?: StorageScope, defaultValue?: string): string {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an element stored with the given key from local storage. Use
|
||||
* the provided defaultValue if the element is null or undefined. The element
|
||||
* will be converted to a number using parseInt with a base of 10.
|
||||
*
|
||||
* The optional scope argument allows to define the scope of the operation.
|
||||
*/
|
||||
getInteger(key: string, scope?: StorageScope, defaultValue?: number): number {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an element stored with the given key from local storage. Use
|
||||
* the provided defaultValue if the element is null or undefined. The element
|
||||
* will be converted to a boolean.
|
||||
*
|
||||
* The optional scope argument allows to define the scope of the operation.
|
||||
*/
|
||||
getBoolean(key: string, scope?: StorageScope, defaultValue?: boolean): boolean {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
27
src/sqltest/stubs/telemetryServiceStub.ts
Normal file
27
src/sqltest/stubs/telemetryServiceStub.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { ITelemetryService, ITelemetryData, ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
|
||||
// Test stubs for commonly used objects
|
||||
|
||||
export class TelemetryServiceStub implements ITelemetryService {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
/**
|
||||
* Sends a telemetry event that has been privacy approved.
|
||||
* Do not call this unless you have been given approval.
|
||||
*/
|
||||
publicLog(eventName: string, data?: ITelemetryData): TPromise<void> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getTelemetryInfo(): TPromise<ITelemetryInfo> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
isOptedIn: boolean;
|
||||
}
|
||||
43
src/sqltest/stubs/themeTestService.ts
Normal file
43
src/sqltest/stubs/themeTestService.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import { IThemeService, ITheme, IThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ColorIdentifier } from 'vs/platform/theme/common/colorRegistry';
|
||||
|
||||
export class TestTheme implements ITheme {
|
||||
selector: string;
|
||||
type: 'light' | 'dark' | 'hc';
|
||||
|
||||
getColor(color: string, useDefault?: boolean): Color {
|
||||
return Color.white;
|
||||
}
|
||||
|
||||
isDefault(color: string): boolean {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
defines(color: ColorIdentifier): boolean {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
|
||||
const testTheme = new TestTheme();
|
||||
|
||||
export class TestThemeService implements IThemeService {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
getTheme(): ITheme {
|
||||
return testTheme;
|
||||
}
|
||||
|
||||
onThemeChange(participant: IThemingParticipant): IDisposable {
|
||||
return { dispose: () => { } };
|
||||
}
|
||||
}
|
||||
107
src/sqltest/stubs/workbenchEditorTestService.ts
Normal file
107
src/sqltest/stubs/workbenchEditorTestService.ts
Normal file
@@ -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.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IEditorService, IEditor, IEditorInput, IEditorOptions, ITextEditorOptions, Position, Direction, IResourceInput, IResourceDiffInput, IResourceSideBySideInput }
|
||||
from 'vs/platform/editor/common/editor';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
|
||||
import { EditorInput, EditorOptions, IFileEditorInput, TextEditorOptions, IEditorRegistry, Extensions, SideBySideEditorInput } from 'vs/workbench/common/editor';
|
||||
|
||||
export class WorkbenchEditorTestService implements IWorkbenchEditorService {
|
||||
_serviceBrand: ServiceIdentifier<any>;
|
||||
|
||||
/**
|
||||
* Returns the currently active editor or null if none.
|
||||
*/
|
||||
getActiveEditor(): IEditor {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently active editor input or null if none.
|
||||
*/
|
||||
getActiveEditorInput(): IEditorInput {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of visible editors.
|
||||
*/
|
||||
getVisibleEditors(): IEditor[] {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns iff the provided input is currently visible.
|
||||
*
|
||||
* @param includeDiff iff set to true, will also consider diff editors to find out if the provided
|
||||
* input is opened either on the left or right hand side of the diff editor.
|
||||
*/
|
||||
isVisible(input: IEditorInput, includeDiff: boolean): boolean {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
protected doOpenEditor(input: IEditorInput, options?: EditorOptions, sideBySide?: boolean): TPromise<IEditor>;
|
||||
protected doOpenEditor(input: IEditorInput, options?: EditorOptions, position?: Position): TPromise<IEditor>;
|
||||
protected doOpenEditor(input: IEditorInput, options?: EditorOptions, arg3?: any): TPromise<IEditor> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens an Editor on the given input with the provided options at the given position. If sideBySide parameter
|
||||
* is provided, causes the editor service to decide in what position to open the input.
|
||||
*/
|
||||
public openEditor(input: IEditorInput, options?: IEditorOptions, sideBySide?: boolean): TPromise<IEditor>;
|
||||
public openEditor(input: IEditorInput, options?: IEditorOptions, position?: Position): TPromise<IEditor>;
|
||||
public openEditor(input: IResourceInput | IResourceDiffInput | IResourceSideBySideInput, position?: Position): TPromise<IEditor>;
|
||||
public openEditor(input: IResourceInput | IResourceDiffInput | IResourceSideBySideInput, sideBySide?: boolean): TPromise<IEditor>;
|
||||
public openEditor(input: any, arg2?: any, arg3?: any): TPromise<IEditor> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public openEditors(editors: { input: IResourceInput | IResourceDiffInput | IResourceSideBySideInput, position: Position }[]): TPromise<IEditor[]>;
|
||||
public openEditors(editors: { input: IEditorInput, position: Position, options?: IEditorOptions }[]): TPromise<IEditor[]>;
|
||||
public openEditors(editors: any[]): TPromise<IEditor[]> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public replaceEditors(editors: { toReplace: IResourceInput | IResourceDiffInput | IResourceSideBySideInput, replaceWith: IResourceInput | IResourceDiffInput | IResourceSideBySideInput }[], position?: Position): TPromise<BaseEditor[]>;
|
||||
public replaceEditors(editors: { toReplace: IEditorInput, replaceWith: IEditorInput, options?: IEditorOptions }[], position?: Position): TPromise<BaseEditor[]>;
|
||||
public replaceEditors(editors: any[], position?: Position): TPromise<BaseEditor[]> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the editor at the provided position.
|
||||
*/
|
||||
closeEditor(position: Position, input: IEditorInput): TPromise<void> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes editors of a specific group at the provided position. If the optional editor is provided to exclude, it
|
||||
* will not be closed. The direction can be used in that case to control if all other editors should get closed,
|
||||
* or towards a specific direction.
|
||||
*/
|
||||
closeEditors(position: Position, filter?: { except?: IEditorInput, direction?: Direction, unmodifiedOnly?: boolean }): TPromise<void> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes all editors across all groups. The optional position allows to keep one group alive.
|
||||
*/
|
||||
closeAllEditors(except?: Position): TPromise<void> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to resolve an untyped input to a workbench typed instanceof editor input
|
||||
*/
|
||||
createInput(input: IResourceInput | IResourceDiffInput | IResourceSideBySideInput): IEditorInput {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
80
src/sqltest/stubs/workspaceConfigurationTestService.ts
Normal file
80
src/sqltest/stubs/workspaceConfigurationTestService.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import {
|
||||
IConfigurationValue, IConfigurationData, IConfigurationKeys,
|
||||
IConfigurationServiceEvent, IConfigurationValues } from 'vs/platform/configuration/common/configuration';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import Event from 'vs/base/common/event';
|
||||
|
||||
export class WorkspaceConfigurationTestService implements IWorkspaceConfigurationService {
|
||||
_serviceBrand: any;
|
||||
|
||||
|
||||
getConfigurationData<T>(): IConfigurationData<T> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns untrusted configuration keys for the current workspace.
|
||||
*/
|
||||
getUnsupportedWorkspaceKeys(): string[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns iff the workspace has configuration or not.
|
||||
*/
|
||||
hasWorkspaceConfiguration(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns untrusted configuration keys for the current workspace.
|
||||
*/
|
||||
getUntrustedConfigurations(): string[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the user explicitly configured to not trust the current workspace.
|
||||
*/
|
||||
isExplicitlyUntrusted(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override for the IConfigurationService#lookup() method that adds information about workspace settings.
|
||||
*/
|
||||
lookup<T>(key: string): IConfigurationValue<T> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getConfiguration<T>(section?: string): T {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
reloadConfiguration<T>(section?: string): TPromise<T> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override for the IConfigurationService#keys() method that adds information about workspace settings.
|
||||
*/
|
||||
keys(): IConfigurationKeys {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the defined values of configurations in the different scopes.
|
||||
*/
|
||||
values(): IConfigurationValues {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
onDidUpdateConfiguration: Event<IConfigurationServiceEvent>;
|
||||
}
|
||||
87
src/sqltest/utils/eventVerifier.ts
Normal file
87
src/sqltest/utils/eventVerifier.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
|
||||
export class EventVerifierSingle<T> {
|
||||
private _eventArgument: T;
|
||||
private _eventFired: boolean;
|
||||
|
||||
constructor() {
|
||||
this._eventFired = false;
|
||||
}
|
||||
|
||||
public get eventArgument(): T {
|
||||
return this._eventArgument;
|
||||
}
|
||||
|
||||
public get eventFired(): boolean {
|
||||
return this._eventFired;
|
||||
}
|
||||
|
||||
public assertFired(expectedArgument?: T) {
|
||||
assert.ok(this._eventFired);
|
||||
if (expectedArgument) {
|
||||
assert.equal(this._eventArgument, expectedArgument);
|
||||
}
|
||||
}
|
||||
|
||||
public assertFiredWithVerify(argumentVerification: (arg: T) => void) {
|
||||
assert.ok(this._eventFired);
|
||||
argumentVerification(this._eventArgument);
|
||||
}
|
||||
|
||||
public assertNotFired() {
|
||||
assert.equal(this._eventFired, false);
|
||||
}
|
||||
|
||||
public get eventHandler(): (arg: T) => void {
|
||||
let self = this;
|
||||
return (arg: T) => {
|
||||
self._eventArgument = arg;
|
||||
self._eventFired = true;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class EventVerifierMultiple<T> {
|
||||
private _eventArguments: T[];
|
||||
|
||||
constructor() {
|
||||
this._eventArguments = [];
|
||||
}
|
||||
|
||||
public get eventArguments(): T[] {
|
||||
return this._eventArguments;
|
||||
}
|
||||
|
||||
public get eventFired(): boolean {
|
||||
return this._eventArguments.length > 0;
|
||||
}
|
||||
|
||||
public assertFired(expectedArgument?: T) {
|
||||
assert.ok(this.eventFired);
|
||||
if (expectedArgument) {
|
||||
assert.ok(this._eventArguments.includes(expectedArgument));
|
||||
}
|
||||
}
|
||||
|
||||
public assertNotFired(expectedArgument?: T) {
|
||||
if (expectedArgument) {
|
||||
assert.ok(!this._eventArguments.includes(expectedArgument));
|
||||
} else {
|
||||
assert.ok(!this.eventFired);
|
||||
}
|
||||
}
|
||||
|
||||
public eventHandler(): (arg: T) => void {
|
||||
let self = this;
|
||||
return (arg: T) => {
|
||||
self._eventArguments.push(arg);
|
||||
};
|
||||
}
|
||||
}
|
||||
273
src/sqltest/workbench/api/extHostAccountManagement.test.ts
Normal file
273
src/sqltest/workbench/api/extHostAccountManagement.test.ts
Normal file
@@ -0,0 +1,273 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as data from 'data';
|
||||
import * as TypeMoq from 'typemoq';
|
||||
import { AccountProviderStub, AccountManagementTestService } from 'sqltest/stubs/accountManagementStubs';
|
||||
import { ExtHostAccountManagement } from 'sql/workbench/api/node/extHostAccountManagement';
|
||||
import { TestThreadService } from 'vs/workbench/test/electron-browser/api/testThreadService';
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
|
||||
import { SqlMainContext } from 'sql/workbench/api/node/sqlExtHost.protocol';
|
||||
import { MainThreadAccountManagement } from 'sql/workbench/api/node/mainThreadAccountManagement';
|
||||
import { IAccountManagementService } from 'sql/services/accountManagement/interfaces';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
const IThreadService = createDecorator<IThreadService>('threadService');
|
||||
|
||||
// SUITE STATE /////////////////////////////////////////////////////////////
|
||||
let instantiationService: TestInstantiationService;
|
||||
let mockAccountMetadata: data.AccountProviderMetadata;
|
||||
let mockAccount: data.Account;
|
||||
let threadService: TestThreadService;
|
||||
|
||||
// TESTS ///////////////////////////////////////////////////////////////////
|
||||
suite('ExtHostAccountManagement', () => {
|
||||
suiteSetup(() => {
|
||||
threadService = new TestThreadService();
|
||||
const accountMgmtStub = new AccountManagementTestService();
|
||||
|
||||
instantiationService = new TestInstantiationService();
|
||||
instantiationService.stub(IThreadService, threadService);
|
||||
instantiationService.stub(IAccountManagementService, accountMgmtStub);
|
||||
|
||||
const accountMgmtService = instantiationService.createInstance(MainThreadAccountManagement);
|
||||
threadService.setTestInstance(SqlMainContext.MainThreadAccountManagement, accountMgmtService);
|
||||
|
||||
mockAccountMetadata = {
|
||||
args: {},
|
||||
displayName: 'Test Account Provider',
|
||||
id: 'test_account_provider',
|
||||
settings: {}
|
||||
};
|
||||
mockAccount = {
|
||||
key: {
|
||||
providerId: mockAccountMetadata.id,
|
||||
providerArgs: {},
|
||||
accountId: 'test_account'
|
||||
},
|
||||
properties: {},
|
||||
displayInfo: {
|
||||
displayName: 'Test Account',
|
||||
contextualDisplayName: 'Test Kind Of Account',
|
||||
contextualLogo: { light: '', dark: '' }
|
||||
},
|
||||
isStale: false
|
||||
};
|
||||
});
|
||||
|
||||
test('Constructor', () => {
|
||||
// If: I construct a new extension host account management
|
||||
let extHost = new ExtHostAccountManagement(threadService);
|
||||
|
||||
// Then: There shouldn't be any account providers registered
|
||||
assert.equal(extHost.getProviderCount(), 0);
|
||||
});
|
||||
|
||||
// REGISTER TESTS //////////////////////////////////////////////////////
|
||||
test('Register Account Provider - Success', () => {
|
||||
// Setup: Create an extension host account management
|
||||
let extHost = new ExtHostAccountManagement(threadService);
|
||||
let mockProvider = getMockAccountProvider();
|
||||
|
||||
// If: I register a mock account provider
|
||||
extHost.$registerAccountProvider(mockAccountMetadata, mockProvider.object);
|
||||
|
||||
// Then: The account provider should be registered
|
||||
assert.equal(extHost.getProviderCount(), 1);
|
||||
});
|
||||
|
||||
test('Register Account Provider - Account Provider Already Registered', () => {
|
||||
// Setup: Create an extension host account management and register an account provider
|
||||
let extHost = new ExtHostAccountManagement(threadService);
|
||||
let mockProvider = getMockAccountProvider();
|
||||
extHost.$registerAccountProvider(mockAccountMetadata, mockProvider.object);
|
||||
|
||||
// If: I register an account provider again
|
||||
// Then
|
||||
// ... It should throw
|
||||
assert.throws(() => {
|
||||
extHost.$registerAccountProvider(mockAccountMetadata, mockProvider.object);
|
||||
});
|
||||
|
||||
// ... There should only be one account provider
|
||||
assert.equal(extHost.getProviderCount(), 1);
|
||||
});
|
||||
|
||||
// TODO: Test for unregistering a provider
|
||||
|
||||
// CLEAR TESTS /////////////////////////////////////////////////////////
|
||||
test('Clear - Success', (done) => {
|
||||
// Setup: Create ext host account management with registered account provider
|
||||
let extHost = new ExtHostAccountManagement(threadService);
|
||||
let mockProvider = getMockAccountProvider();
|
||||
extHost.$registerAccountProvider(mockAccountMetadata, mockProvider.object);
|
||||
|
||||
// If: I clear an account
|
||||
extHost.$clear(0, mockAccount.key)
|
||||
.then(() => {
|
||||
// Then: The call should have been passed to the provider
|
||||
mockProvider.verify(
|
||||
(obj) => obj.clear(TypeMoq.It.isValue(mockAccount.key)),
|
||||
TypeMoq.Times.once()
|
||||
);
|
||||
})
|
||||
.then(() => done(), (err) => done(err));
|
||||
});
|
||||
|
||||
test('Clear - Handle does not exist', (done) => {
|
||||
// Setup: Create ext host account management with registered account provider
|
||||
let extHost = new ExtHostAccountManagement(threadService);
|
||||
let mockProvider = getMockAccountProvider();
|
||||
extHost.$registerAccountProvider(mockAccountMetadata, mockProvider.object);
|
||||
|
||||
// If: I clear an account for a handle that doesn't exist
|
||||
// Then: It should fail
|
||||
extHost.$clear(1, mockAccount.key)
|
||||
.then(() => done('Clear succeeded when it should have failed'))
|
||||
.then(null, () => {
|
||||
// The provider's clear should not have been called
|
||||
mockProvider.verify(
|
||||
(obj) => obj.clear(TypeMoq.It.isAny()),
|
||||
TypeMoq.Times.never()
|
||||
);
|
||||
})
|
||||
.then(() => done(), (err) => done(err));
|
||||
});
|
||||
|
||||
// INITIALIZE TESTS ////////////////////////////////////////////////////
|
||||
test('Initialize - Success', (done) => {
|
||||
// Setup: Create ext host account management with registered account provider
|
||||
let extHost = new ExtHostAccountManagement(threadService);
|
||||
let mockProvider = getMockAccountProvider();
|
||||
extHost.$registerAccountProvider(mockAccountMetadata, mockProvider.object);
|
||||
|
||||
// If: I initialize the provider
|
||||
extHost.$initialize(0, [mockAccount])
|
||||
.then(() => {
|
||||
// Then: The call should have been passed to the provider
|
||||
mockProvider.verify(
|
||||
(obj) => obj.initialize(TypeMoq.It.isValue([mockAccount])),
|
||||
TypeMoq.Times.once()
|
||||
);
|
||||
})
|
||||
.then(() => done(), (err) => done(err));
|
||||
});
|
||||
|
||||
test('Initialize - Handle does not exist', (done) => {
|
||||
// Setup: Create ext host account management with registered account provider
|
||||
let extHost = new ExtHostAccountManagement(threadService);
|
||||
let mockProvider = getMockAccountProvider();
|
||||
extHost.$registerAccountProvider(mockAccountMetadata, mockProvider.object);
|
||||
|
||||
// If: I initialize for a handle that doesn't exist
|
||||
// Then: It should fail
|
||||
extHost.$initialize(1, [mockAccount])
|
||||
.then(() => done('Initialize succeeded when it should have failed'))
|
||||
.then(null, () => {
|
||||
// The provider's clear should not have been called
|
||||
mockProvider.verify(
|
||||
(obj) => obj.initialize(TypeMoq.It.isAny()),
|
||||
TypeMoq.Times.never()
|
||||
);
|
||||
})
|
||||
.then(() => done(), (err) => done(err));
|
||||
});
|
||||
|
||||
// PROMPT TESTS ////////////////////////////////////////////////////////
|
||||
test('Prompt - Success', (done) => {
|
||||
// Setup: Create ext host account management with registered account provider
|
||||
let extHost = new ExtHostAccountManagement(threadService);
|
||||
let mockProvider = getMockAccountProvider();
|
||||
extHost.$registerAccountProvider(mockAccountMetadata, mockProvider.object);
|
||||
|
||||
// If: I prompt for an account
|
||||
extHost.$prompt(0)
|
||||
.then(() => {
|
||||
// Then: The call should have been passed to the provider
|
||||
mockProvider.verify(
|
||||
(obj) => obj.prompt(),
|
||||
TypeMoq.Times.once()
|
||||
);
|
||||
})
|
||||
.then(() => done(), (err) => done(err));
|
||||
});
|
||||
|
||||
test('Prompt - Handle does not exist', (done) => {
|
||||
// Setup: Create ext host account management with registered account provider
|
||||
let extHost = new ExtHostAccountManagement(threadService);
|
||||
let mockProvider = getMockAccountProvider();
|
||||
extHost.$registerAccountProvider(mockAccountMetadata, mockProvider.object);
|
||||
|
||||
// If: I prompt with a handle that doesn't exist
|
||||
// Then: It should fail
|
||||
extHost.$prompt(1)
|
||||
.then(() => done('Prompt succeeded when it should have failed'))
|
||||
.then(null, () => {
|
||||
// The provider's clear should not have been called
|
||||
mockProvider.verify(
|
||||
(obj) => obj.prompt(),
|
||||
TypeMoq.Times.never()
|
||||
);
|
||||
})
|
||||
.then(() => done(), (err) => done(err));
|
||||
});
|
||||
|
||||
// REFRESH TESTS ///////////////////////////////////////////////////////
|
||||
test('Refresh - Success', (done) => {
|
||||
// Setup: Create ext host account management with registered account provider
|
||||
let extHost = new ExtHostAccountManagement(threadService);
|
||||
let mockProvider = getMockAccountProvider();
|
||||
extHost.$registerAccountProvider(mockAccountMetadata, mockProvider.object);
|
||||
|
||||
// If: I refresh an account
|
||||
extHost.$refresh(0, mockAccount)
|
||||
.then(() => {
|
||||
// Then: The call should have been passed to the provider
|
||||
mockProvider.verify(
|
||||
(obj) => obj.refresh(TypeMoq.It.isValue(mockAccount)),
|
||||
TypeMoq.Times.once()
|
||||
);
|
||||
})
|
||||
.then(() => done(), (err) => done(err));
|
||||
});
|
||||
|
||||
test('Refresh - Handle does not exist', (done) => {
|
||||
// Setup: Create ext host account management with registered account provider
|
||||
let extHost = new ExtHostAccountManagement(threadService);
|
||||
let mockProvider = getMockAccountProvider();
|
||||
extHost.$registerAccountProvider(mockAccountMetadata, mockProvider.object);
|
||||
|
||||
// If: I refresh an account for a handle that doesn't exist
|
||||
// Then: It should fail
|
||||
extHost.$refresh(1, mockAccount)
|
||||
.then(() => done('Refresh succeeded when it should have failed'))
|
||||
.then(null, () => {
|
||||
// The provider's clear should not have been called
|
||||
mockProvider.verify(
|
||||
(obj) => obj.refresh(TypeMoq.It.isAny()),
|
||||
TypeMoq.Times.never()
|
||||
);
|
||||
})
|
||||
.then(() => done(), (err) => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
function getMockAccountProvider(): TypeMoq.Mock<data.AccountProvider> {
|
||||
let mock = TypeMoq.Mock.ofType<data.AccountProvider>(AccountProviderStub);
|
||||
mock.setup((obj) => obj.clear(TypeMoq.It.isValue(mockAccount.key)))
|
||||
.returns(() => Promise.resolve(undefined));
|
||||
mock.setup((obj) => obj.refresh(TypeMoq.It.isValue(mockAccount)))
|
||||
.returns(() => Promise.resolve(undefined));
|
||||
mock.setup((obj) => obj.initialize(TypeMoq.It.isValue([mockAccount])))
|
||||
.returns(() => Promise.resolve(undefined));
|
||||
mock.setup((obj) => obj.prompt())
|
||||
.returns(() => Promise.resolve(undefined));
|
||||
|
||||
return mock;
|
||||
}
|
||||
133
src/sqltest/workbench/api/extHostCredentialManagement.test.ts
Normal file
133
src/sqltest/workbench/api/extHostCredentialManagement.test.ts
Normal file
@@ -0,0 +1,133 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import {TestThreadService} from 'vs/workbench/test/electron-browser/api/testThreadService';
|
||||
import {TestInstantiationService} from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import {ExtHostCredentialManagement} from 'sql/workbench/api/node/extHostCredentialManagement';
|
||||
import {SqlMainContext} from 'sql/workbench/api/node/sqlExtHost.protocol';
|
||||
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
|
||||
import {MainThreadCredentialManagement} from 'sql/workbench/api/node/mainThreadCredentialManagement';
|
||||
import {CredentialsTestProvider, CredentialsTestService} from 'sqltest/stubs/credentialsTestStubs';
|
||||
import {ICredentialsService} from 'sql/services/credentials/credentialsService';
|
||||
import {Credential, CredentialProvider} from 'data';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
const IThreadService = createDecorator<IThreadService>('threadService');
|
||||
|
||||
// SUITE STATE /////////////////////////////////////////////////////////////
|
||||
let credentialServiceStub: CredentialsTestService;
|
||||
let instantiationService: TestInstantiationService;
|
||||
let threadService: TestThreadService;
|
||||
|
||||
// TESTS ///////////////////////////////////////////////////////////////////
|
||||
suite('ExtHostCredentialManagement', () => {
|
||||
suiteSetup(() => {
|
||||
threadService = new TestThreadService();
|
||||
credentialServiceStub = new CredentialsTestService();
|
||||
|
||||
instantiationService = new TestInstantiationService();
|
||||
instantiationService.stub(IThreadService, threadService);
|
||||
instantiationService.stub(ICredentialsService, credentialServiceStub);
|
||||
|
||||
const credentialService = instantiationService.createInstance(MainThreadCredentialManagement);
|
||||
threadService.setTestInstance(SqlMainContext.MainThreadCredentialManagement, credentialService);
|
||||
});
|
||||
|
||||
test('Construct ExtHostCredentialManagement', () => {
|
||||
// If: I construct an credential management extension host
|
||||
let extHost = new ExtHostCredentialManagement(threadService);
|
||||
|
||||
// Then: The extension host should not have any providers registered
|
||||
assert.equal(extHost.getProviderCount(), 0);
|
||||
});
|
||||
|
||||
test('Register Credential Provider', () => {
|
||||
// Setup: Create a mock credential provider
|
||||
let extHost = new ExtHostCredentialManagement(threadService);
|
||||
let mockCredentialProvider = new CredentialsTestProvider();
|
||||
|
||||
// If: I register the credential provider with the extension host
|
||||
extHost.$registerCredentialProvider(mockCredentialProvider);
|
||||
|
||||
// Then: There should be one provider registered
|
||||
assert.equal(extHost.getProviderCount(), 1);
|
||||
});
|
||||
|
||||
test('Get Credential Provider - Success', (done) => {
|
||||
// Setup: Register a mock credential provider
|
||||
let extHost = new ExtHostCredentialManagement(threadService);
|
||||
let mockCredentialProvider = new CredentialsTestProvider();
|
||||
extHost.$registerCredentialProvider(mockCredentialProvider);
|
||||
|
||||
// If: I get the credential provider
|
||||
let namespaceId = 'test_namespace';
|
||||
let credentialId = 'test_id';
|
||||
let credential = 'test_credential';
|
||||
let expectedCredentialId = `${namespaceId}|${credentialId}`;
|
||||
let credProvider: CredentialProvider;
|
||||
extHost.$getCredentialProvider(namespaceId)
|
||||
.then((provider) => {
|
||||
// Then: There should still only be one provider registered
|
||||
assert.equal(extHost.getProviderCount(), 1);
|
||||
credProvider = provider;
|
||||
})
|
||||
.then(() => {
|
||||
// If: I write a credential
|
||||
return credProvider.saveCredential(credentialId, credential);
|
||||
})
|
||||
.then(() => {
|
||||
// Then: The credential should have been stored with its namespace
|
||||
assert.notStrictEqual(mockCredentialProvider.storedCredentials[expectedCredentialId], undefined);
|
||||
assert.equal(mockCredentialProvider.storedCredentials[expectedCredentialId].credentialId, expectedCredentialId);
|
||||
assert.equal(mockCredentialProvider.storedCredentials[expectedCredentialId].password, credential);
|
||||
})
|
||||
.then(() => {
|
||||
// If: I read a credential
|
||||
return credProvider.readCredential(credentialId);
|
||||
})
|
||||
.then((returnedCredential: Credential) => {
|
||||
// Then: The credential ID should be namespaced
|
||||
assert.equal(returnedCredential.credentialId, expectedCredentialId);
|
||||
assert.equal(returnedCredential.password, credential);
|
||||
})
|
||||
.then(() => {
|
||||
// If: I delete a credential
|
||||
return credProvider.deleteCredential(credentialId);
|
||||
})
|
||||
.then(() => {
|
||||
// Then: The credential with its namespace should no longer exist
|
||||
assert.strictEqual(mockCredentialProvider.storedCredentials[expectedCredentialId], undefined);
|
||||
})
|
||||
.then(() => done(), (err) => done(err));
|
||||
});
|
||||
|
||||
test('Get Credential Provider - No Namespace', (done) => {
|
||||
// Setup: Register a mock credential provider
|
||||
let extHost = new ExtHostCredentialManagement(threadService);
|
||||
let mockCredentialProvider = new CredentialsTestProvider();
|
||||
extHost.$registerCredentialProvider(mockCredentialProvider);
|
||||
|
||||
// If: I get a credential provider with an invalid namespace ID
|
||||
// Then: I should get an error
|
||||
extHost.$getCredentialProvider(undefined)
|
||||
.then(
|
||||
() => { done('Provider was returned from undefined'); },
|
||||
() => { /* Swallow error, this is success path */ }
|
||||
)
|
||||
.then(() => { return extHost.$getCredentialProvider(null); })
|
||||
.then(
|
||||
() => { done('Provider was returned from null'); },
|
||||
() => { /* Swallow error, this is success path */ }
|
||||
)
|
||||
.then(() => {return extHost.$getCredentialProvider(''); })
|
||||
.then(
|
||||
() => { done('Provider was returned from \'\''); },
|
||||
() => { done(); }
|
||||
);
|
||||
});
|
||||
});
|
||||
129
src/sqltest/workbench/api/extHostDataProtocol.test.ts
Normal file
129
src/sqltest/workbench/api/extHostDataProtocol.test.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { setUnexpectedErrorHandler, errorHandler } from 'vs/base/common/errors';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import * as EditorCommon from 'vs/editor/common/editorCommon';
|
||||
import { Model as EditorModel } from 'vs/editor/common/model/model';
|
||||
import { TestThreadService } from 'vs/workbench/test/electron-browser/api/testThreadService';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IMarkerService } from 'vs/platform/markers/common/markers';
|
||||
import { MarkerService } from 'vs/platform/markers/common/markerService';
|
||||
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
|
||||
import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
|
||||
import { MainThreadCommands } from 'vs/workbench/api/electron-browser/mainThreadCommands';
|
||||
import { IHeapService } from 'vs/workbench/api/electron-browser/mainThreadHeapService';
|
||||
import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
|
||||
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/node/extHostDocumentsAndEditors';
|
||||
import { DocumentSymbolProviderRegistry } from 'vs/editor/common/modes';
|
||||
import { MainContext, ExtHostContext } from 'vs/workbench/api/node/extHost.protocol';
|
||||
import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics';
|
||||
import { ExtHostHeapService } from 'vs/workbench/api/node/extHostHeapService';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
import * as data from 'data';
|
||||
import { ExtHostDataProtocol } from 'sql/workbench/api/node/extHostDataProtocol';
|
||||
import { SqlExtHostContext } from 'sql/workbench/api/node/sqlExtHost.protocol';
|
||||
|
||||
const IThreadService = createDecorator<IThreadService>('threadService');
|
||||
|
||||
const model: EditorCommon.IModel = EditorModel.createFromString(
|
||||
[
|
||||
'This is the first line',
|
||||
'This is the second line',
|
||||
'This is the third line',
|
||||
].join('\n'),
|
||||
undefined,
|
||||
undefined,
|
||||
URI.parse('far://testing/file.a'));
|
||||
|
||||
let extHost: ExtHostDataProtocol;
|
||||
let disposables: vscode.Disposable[] = [];
|
||||
let threadService: TestThreadService;
|
||||
let originalErrorHandler: (e: any) => any;
|
||||
|
||||
suite('ExtHostDataProtocol', function () {
|
||||
|
||||
suiteSetup(() => {
|
||||
|
||||
threadService = new TestThreadService();
|
||||
let instantiationService = new TestInstantiationService();
|
||||
instantiationService.stub(IThreadService, threadService);
|
||||
instantiationService.stub(IMarkerService, MarkerService);
|
||||
instantiationService.stub(IHeapService, {
|
||||
_serviceBrand: undefined,
|
||||
trackRecursive(args) {
|
||||
// nothing
|
||||
return args;
|
||||
}
|
||||
});
|
||||
|
||||
originalErrorHandler = errorHandler.getUnexpectedErrorHandler();
|
||||
setUnexpectedErrorHandler(() => { });
|
||||
|
||||
const extHostDocumentsAndEditors = new ExtHostDocumentsAndEditors(threadService);
|
||||
extHostDocumentsAndEditors.$acceptDocumentsAndEditorsDelta({
|
||||
addedDocuments: [{
|
||||
isDirty: false,
|
||||
versionId: model.getVersionId(),
|
||||
modeId: model.getLanguageIdentifier().language,
|
||||
url: model.uri,
|
||||
lines: model.getValue().split(model.getEOL()),
|
||||
EOL: model.getEOL(),
|
||||
}]
|
||||
});
|
||||
const extHostDocuments = new ExtHostDocuments(threadService, extHostDocumentsAndEditors);
|
||||
threadService.set(ExtHostContext.ExtHostDocuments, extHostDocuments);
|
||||
|
||||
const heapService = new ExtHostHeapService();
|
||||
|
||||
const commands = new ExtHostCommands(threadService, heapService);
|
||||
threadService.set(ExtHostContext.ExtHostCommands, commands);
|
||||
threadService.setTestInstance(MainContext.MainThreadCommands, instantiationService.createInstance(MainThreadCommands));
|
||||
|
||||
const diagnostics = new ExtHostDiagnostics(threadService);
|
||||
threadService.set(ExtHostContext.ExtHostDiagnostics, diagnostics);
|
||||
|
||||
extHost = new ExtHostDataProtocol(threadService);
|
||||
threadService.set(SqlExtHostContext.ExtHostDataProtocol, extHost);
|
||||
});
|
||||
|
||||
suiteTeardown(() => {
|
||||
setUnexpectedErrorHandler(originalErrorHandler);
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
teardown(function () {
|
||||
while (disposables.length) {
|
||||
disposables.pop().dispose();
|
||||
}
|
||||
return threadService.sync();
|
||||
});
|
||||
|
||||
// --- outline
|
||||
|
||||
test('DataProvider, language flavor changed', function () {
|
||||
assert.equal(DocumentSymbolProviderRegistry.all(model).length, 0);
|
||||
let expectedParams = <data.DidChangeLanguageFlavorParams> {
|
||||
uri: 'myuri',
|
||||
language: 'sql'
|
||||
};
|
||||
let actualParams: data.DidChangeLanguageFlavorParams = undefined;
|
||||
extHost.onDidChangeLanguageFlavor((e => {
|
||||
actualParams = e;
|
||||
}));
|
||||
|
||||
extHost.$languageFlavorChanged(expectedParams);
|
||||
|
||||
assert.ok(actualParams !== undefined);
|
||||
assert.equal(actualParams.uri, expectedParams.uri);
|
||||
assert.equal(actualParams.flavor, expectedParams.flavor);
|
||||
assert.equal(actualParams.language, expectedParams.language);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user