Public api changes to namespace accounts & connection. (#2383)

* 1.Added following functions to namespace accounts
function getAllAccounts(): Thenable<AccountWithProviderHandle[]>;
function getSecurityToken(account: AccountWithProviderHandle): Thenable<{}>;
2.Added class AccountWithProviderHandle as the wrapper for Account
3.Changed function openConnectionDialog of namespace connection to allow connection dialog initialized with specified parameters, i.e., server name, database name, etc.
function openConnectionDialog(provider?: string[], initialConnectionProfile?: IConnectionProfile): Thenable<connection.Connection>;

* Added unit tests for ExtHostAccountManagement.$getAllAccounts
This commit is contained in:
Vincent Feng
2018-09-03 11:48:00 +08:00
committed by GitHub
parent b27f69aace
commit 8600dbb04e
9 changed files with 170 additions and 9 deletions

28
src/sql/sqlops.d.ts vendored
View File

@@ -1848,6 +1848,19 @@ declare module 'sqlops' {
* @param {Account} updatedAccount Account object with updated properties
*/
export function accountUpdated(updatedAccount: Account): void;
/**
* Gets all added accounts.
* @returns {Thenable<Account>} Promise to return the accounts
*/
export function getAllAccounts(): Thenable<AccountWithProviderHandle[]>;
/**
* Generates a security token by asking the account's provider
* @param {Account} account Account to generate security token for
* @return {Thenable<{}>} Promise to return the security token
*/
export function getSecurityToken(account: AccountWithProviderHandle): Thenable<{}>;
}
/**
@@ -1915,6 +1928,21 @@ declare module 'sqlops' {
isStale: boolean;
}
/**
* Represents an account with account provider's handle
*/
export interface AccountWithProviderHandle {
/**
* Account
*/
account: Account;
/**
* Account's provider handle
*/
providerHandle: number;
}
// - ACCOUNT PROVIDER //////////////////////////////////////////////////
/**
* Error to be used when the user has cancelled the prompt or refresh methods. When

View File

@@ -1220,6 +1220,6 @@ declare module 'sqlops' {
* returns the connection otherwise returns undefined
* @param callback
*/
export function openConnectionDialog(provider?: string[]): Thenable<connection.Connection>;
export function openConnectionDialog(provider?: string[], initialConnectionProfile?: IConnectionProfile): Thenable<connection.Connection>;
}
}

View File

@@ -64,6 +64,33 @@ export class ExtHostAccountManagement extends ExtHostAccountManagementShape {
this._proxy.$accountUpdated(updatedAccount);
}
public $getAllAccounts(): Thenable<sqlops.AccountWithProviderHandle[]> {
if (Object.keys(this._providers).length === 0) {
throw new Error('No account providers registered.');
}
let accountWithProviderHandles: sqlops.AccountWithProviderHandle[] = [];
let promises: Thenable<void>[] = [];
for (let providerKey in this._providers) {
let providerHandle = parseInt(providerKey);
let provider = this._providers[providerHandle];
promises.push(this._proxy.$getAccountsForProvider(provider.metadata.id).then(
(accounts) => {
accounts.forEach((account) => {
accountWithProviderHandles.push({
account: account,
providerHandle: providerHandle
});
});
}
));
}
return Promise.all(promises).then(() => accountWithProviderHandles);
}
public $registerAccountProvider(providerMetadata: sqlops.AccountProviderMetadata, provider: sqlops.AccountProvider): Disposable {
let self = this;

View File

@@ -32,8 +32,8 @@ export class ExtHostConnectionManagement extends ExtHostConnectionManagementShap
return this._proxy.$getCredentials(connectionId);
}
public $openConnectionDialog(providers?: string[]): Thenable<sqlops.connection.Connection> {
return this._proxy.$openConnectionDialog(providers);
public $openConnectionDialog(providers?: string[], initialConnectionProfile?: sqlops.IConnectionProfile): Thenable<sqlops.connection.Connection> {
return this._proxy.$openConnectionDialog(providers, initialConnectionProfile);
}
public $listDatabases(connectionId: string): Thenable<string[]> {

View File

@@ -46,6 +46,10 @@ export class MainThreadAccountManagement implements MainThreadAccountManagementS
this._accountManagementService.accountUpdated(updatedAccount);
}
public $getAccountsForProvider(providerId: string): Thenable<sqlops.Account[]> {
return this._accountManagementService.getAccountsForProvider(providerId);
}
public $registerAccountProvider(providerMetadata: sqlops.AccountProviderMetadata, handle: number): Thenable<any> {
let self = this;

View File

@@ -51,8 +51,8 @@ export class MainThreadConnectionManagement implements MainThreadConnectionManag
}
public async $openConnectionDialog(providers: string[]): Promise<sqlops.connection.Connection> {
let connectionProfile = await this._connectionDialogService.openDialogAndWait(this._connectionManagementService, { connectionType: 1, providers: providers });
public async $openConnectionDialog(providers: string[], initialConnectionProfile?: IConnectionProfile): Promise<sqlops.connection.Connection> {
let connectionProfile = await this._connectionDialogService.openDialogAndWait(this._connectionManagementService, { connectionType: 1, providers: providers }, initialConnectionProfile);
return connectionProfile ? {
connectionId: connectionProfile.id,
options: connectionProfile.options,

View File

@@ -90,6 +90,12 @@ export function createApiFactory(
},
accountUpdated(updatedAccount: sqlops.Account): void {
return extHostAccountManagement.$accountUpdated(updatedAccount);
},
getAllAccounts(): Thenable<sqlops.AccountWithProviderHandle[]> {
return extHostAccountManagement.$getAllAccounts();
},
getSecurityToken(account: sqlops.AccountWithProviderHandle): Thenable<{}> {
return extHostAccountManagement.$getSecurityToken(account.providerHandle, account.account);
}
};
@@ -104,8 +110,8 @@ export function createApiFactory(
getCredentials(connectionId: string): Thenable<{ [name: string]: string }> {
return extHostConnectionManagement.$getCredentials(connectionId);
},
openConnectionDialog(providers?: string[]): Thenable<sqlops.connection.Connection> {
return extHostConnectionManagement.$openConnectionDialog(providers);
openConnectionDialog(providers?: string[], initialConnectionProfile?: sqlops.IConnectionProfile): Thenable<sqlops.connection.Connection> {
return extHostConnectionManagement.$openConnectionDialog(providers, initialConnectionProfile);
},
listDatabases(connectionId: string): Thenable<string[]> {
return extHostConnectionManagement.$listDatabases(connectionId);

View File

@@ -446,6 +446,8 @@ export interface MainThreadAccountManagementShape extends IDisposable {
$endAutoOAuthDeviceCode(): void;
$accountUpdated(updatedAccount: sqlops.Account): void;
$getAccountsForProvider(providerId: string): Thenable<sqlops.Account[]>;
}
export interface MainThreadResourceProviderShape extends IDisposable {
@@ -499,7 +501,7 @@ export interface MainThreadConnectionManagementShape extends IDisposable {
$getActiveConnections(): Thenable<sqlops.connection.Connection[]>;
$getCurrentConnection(): Thenable<sqlops.connection.Connection>;
$getCredentials(connectionId: string): Thenable<{ [name: string]: string }>;
$openConnectionDialog(providers: string[]): Thenable<sqlops.connection.Connection>;
$openConnectionDialog(providers: string[], initialConnectionProfile?: sqlops.IConnectionProfile): Thenable<sqlops.connection.Connection>;
$listDatabases(connectionId: string): Thenable<string[]>;
$getConnectionString(connectionId: string, includePassword: boolean): Thenable<string>;
$getUriForConnection(connectionId: string): Thenable<string>;
@@ -687,4 +689,4 @@ export interface ExtHostQueryEditorShape {
export interface MainThreadQueryEditorShape extends IDisposable {
$connect(fileUri: string, connectionId: string): Thenable<void>;
$runQuery(fileUri: string): void;
}
}

View File

@@ -256,6 +256,91 @@ suite('ExtHostAccountManagement', () => {
})
.then(() => done(), (err) => done(err));
});
// GETALLACCOUNTS TESTS ///////////////////////////////////////////////////////
test('GetAllAccounts - Success', (done) => {
let mockAccountProviderMetadata = {
id: 'azure',
displayName: 'Azure'
};
let mockAccount1 = {
key: {
providerId: mockAccountProviderMetadata.id,
accountId: 'azure_account_1'
},
displayInfo: {
contextualDisplayName: 'Microsoft Account',
accountType: 'microsoft',
displayName: 'Azure Account 1'
},
properties: [],
isStale: false
};
let mockAccount2 = {
key: {
providerId: mockAccountProviderMetadata.id,
accountId: 'azure_account_2'
},
displayInfo: {
contextualDisplayName: 'Work/School Account',
accountType: 'microsoft',
displayName: 'Azure Account 2'
},
properties: [],
isStale: false
};
let mockAccounts = [mockAccount1, mockAccount2];
let expectedAccounts = [
{
account: mockAccount1,
providerHandle: 0
},
{
account: mockAccount2,
providerHandle: 0
}
];
let mockAccountManagementService = getMockAccountManagementService(mockAccounts);
instantiationService.stub(IAccountManagementService, mockAccountManagementService.object);
let accountManagementService = instantiationService.createInstance(MainThreadAccountManagement);
threadService.set(SqlMainContext.MainThreadAccountManagement, accountManagementService);
// Setup: Create ext host account management with registered account provider
let extHost = new ExtHostAccountManagement(threadService);
extHost.$registerAccountProvider(mockAccountProviderMetadata, new AccountProviderStub());
// If: I get all accounts
extHost.$getAllAccounts()
.then((accounts) => {
// Then: The call should have been passed to the account management service
mockAccountManagementService.verify(
(obj) => obj.getAccountsForProvider(TypeMoq.It.isAny()),
TypeMoq.Times.once()
);
assert.ok(Array.isArray(accounts));
assert.equal(accounts.length, expectedAccounts.length);
assert.deepStrictEqual(accounts, expectedAccounts);
})
.then(() => done(), (err) => done(err));
});
test('GetAllAccounts - No account providers', (done) => {
// Setup: Create ext host account management with no registered account providers
let extHost = new ExtHostAccountManagement(threadService);
// If: I get all accounts
// Then: It should throw
assert.throws(
() => extHost.$getAllAccounts(),
(error) => {
return error.message === 'No account providers registered.';
});
done();
});
});
function getMockAccountProvider(): TypeMoq.Mock<sqlops.AccountProvider> {
@@ -271,3 +356,12 @@ function getMockAccountProvider(): TypeMoq.Mock<sqlops.AccountProvider> {
return mock;
}
function getMockAccountManagementService(accounts: sqlops.Account[]): TypeMoq.Mock<AccountManagementTestService> {
let mockAccountManagementService = TypeMoq.Mock.ofType(AccountManagementTestService);
mockAccountManagementService.setup(x => x.getAccountsForProvider(TypeMoq.It.isAny()))
.returns(() => Promise.resolve(accounts));
return mockAccountManagementService;
}