mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-22 01:25:38 -05:00
Remove sql-bindings logic from sql-database-projects (#18754)
* remove sql-bindings logic from sql-database-projects
This commit is contained in:
@@ -1,134 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as should from 'should';
|
||||
import * as sinon from 'sinon';
|
||||
import * as vscode from 'vscode';
|
||||
import * as TypeMoq from 'typemoq';
|
||||
import * as utils from '../../common/utils';
|
||||
import * as constants from '../../common/constants';
|
||||
import * as azureFunctionUtils from '../../common/azureFunctionsUtils';
|
||||
|
||||
import { createContext, TestContext, createTestCredentials } from '../testContext';
|
||||
import { launchAddSqlBindingQuickpick } from '../../dialogs/addSqlBindingQuickpick';
|
||||
import { PackageHelper } from '../../tools/packageHelper';
|
||||
|
||||
let testContext: TestContext;
|
||||
let packageHelper: PackageHelper;
|
||||
describe('Add SQL Binding quick pick', () => {
|
||||
beforeEach(function (): void {
|
||||
testContext = createContext();
|
||||
packageHelper = new PackageHelper(testContext.outputChannel);
|
||||
});
|
||||
|
||||
afterEach(function (): void {
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
it('Should show error if the file contains no Azure Functions', async function (): Promise<void> {
|
||||
sinon.stub(utils, 'getAzureFunctionService').resolves(testContext.azureFunctionService.object);
|
||||
sinon.stub(utils, 'getVscodeMssqlApi').resolves(testContext.vscodeMssqlIExtension.object);
|
||||
const spy = sinon.spy(vscode.window, 'showErrorMessage');
|
||||
testContext.azureFunctionService.setup(x => x.getAzureFunctions(TypeMoq.It.isAny())).returns(async () => {
|
||||
return Promise.resolve({
|
||||
success: true,
|
||||
errorMessage: '',
|
||||
azureFunctions: []
|
||||
});
|
||||
});
|
||||
await launchAddSqlBindingQuickpick(vscode.Uri.file('testUri'), packageHelper);
|
||||
|
||||
const msg = constants.noAzureFunctionsInFile;
|
||||
should(spy.calledOnce).be.true('showErrorMessage should have been called exactly once');
|
||||
should(spy.calledWith(msg)).be.true(`showErrorMessage not called with expected message '${msg}' Actual '${spy.getCall(0).args[0]}'`);
|
||||
});
|
||||
|
||||
it('Should show error if adding SQL binding was not successful', async function (): Promise<void> {
|
||||
sinon.stub(utils, 'getAzureFunctionService').resolves(testContext.azureFunctionService.object);
|
||||
sinon.stub(utils, 'getVscodeMssqlApi').resolves(testContext.vscodeMssqlIExtension.object);
|
||||
const spy = sinon.spy(vscode.window, 'showErrorMessage');
|
||||
testContext.azureFunctionService.setup(x => x.getAzureFunctions(TypeMoq.It.isAny())).returns(async () => {
|
||||
return Promise.resolve({
|
||||
success: true,
|
||||
errorMessage: '',
|
||||
azureFunctions: ['af1', 'af2']
|
||||
});
|
||||
});
|
||||
//failure since no AFs are found in the project
|
||||
sinon.stub(azureFunctionUtils, 'getAFProjectContainingFile').resolves(undefined);
|
||||
const errormsg = 'Error inserting binding';
|
||||
testContext.azureFunctionService.setup(x => x.addSqlBinding(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(async () => {
|
||||
return Promise.resolve({
|
||||
success: false,
|
||||
errorMessage: errormsg
|
||||
});
|
||||
});
|
||||
|
||||
// select Azure function
|
||||
let quickpickStub = sinon.stub(vscode.window, 'showQuickPick').onFirstCall().resolves({ label: 'af1' });
|
||||
// select input or output binding
|
||||
quickpickStub.onSecondCall().resolves({ label: constants.input });
|
||||
// give object name
|
||||
let inputBoxStub = sinon.stub(vscode.window, 'showInputBox').onFirstCall().resolves('dbo.table1');
|
||||
// give connection string setting name
|
||||
inputBoxStub.onSecondCall().resolves('sqlConnectionString');
|
||||
|
||||
await launchAddSqlBindingQuickpick(vscode.Uri.file('testUri'), packageHelper);
|
||||
|
||||
should(spy.calledOnce).be.true('showErrorMessage should have been called exactly once');
|
||||
should(spy.calledWith(errormsg)).be.true(`showErrorMessage not called with expected message '${errormsg}' Actual '${spy.getCall(0).args[0]}'`);
|
||||
});
|
||||
|
||||
it('Should show error connection profile does not connect', async function (): Promise<void> {
|
||||
sinon.stub(utils, 'getAzureFunctionService').resolves(testContext.azureFunctionService.object);
|
||||
sinon.stub(utils, 'getVscodeMssqlApi').resolves(testContext.vscodeMssqlIExtension.object);
|
||||
let connectionCreds = createTestCredentials();
|
||||
|
||||
sinon.stub(azureFunctionUtils, 'getAFProjectContainingFile').resolves(vscode.Uri.file('testUri'));
|
||||
testContext.azureFunctionService.setup(x => x.getAzureFunctions(TypeMoq.It.isAny())).returns(async () => {
|
||||
return Promise.resolve({
|
||||
success: true,
|
||||
errorMessage: '',
|
||||
azureFunctions: ['af1']
|
||||
});
|
||||
});
|
||||
|
||||
// Mocks connect call to mssql
|
||||
let error = new Error('Connection Request Failed');
|
||||
testContext.vscodeMssqlIExtension.setup(x => x.connect(TypeMoq.It.isAny(), undefined)).throws(error);
|
||||
|
||||
// Mocks promptForConnection
|
||||
testContext.vscodeMssqlIExtension.setup(x => x.promptForConnection(true)).returns(() => Promise.resolve(connectionCreds));
|
||||
let quickpickStub = sinon.stub(vscode.window, 'showQuickPick');
|
||||
// select Azure function
|
||||
quickpickStub.onFirstCall().resolves({ label: 'af1' });
|
||||
// select input or output binding
|
||||
quickpickStub.onSecondCall().resolves({ label: constants.input });
|
||||
|
||||
// give object name
|
||||
let inputBoxStub = sinon.stub(vscode.window, 'showInputBox').onFirstCall().resolves('dbo.table1');
|
||||
|
||||
// select connection profile
|
||||
quickpickStub.onThirdCall().resolves({ label: constants.createNewLocalAppSettingWithIcon });
|
||||
|
||||
// give connection string setting name
|
||||
inputBoxStub.onSecondCall().resolves('SqlConnectionString');
|
||||
|
||||
// select connection profile method
|
||||
quickpickStub.onCall(3).resolves({ label: constants.connectionProfile });
|
||||
|
||||
await launchAddSqlBindingQuickpick(vscode.Uri.file('testUri'), packageHelper);
|
||||
|
||||
// should go back to the select connection string methods
|
||||
should(quickpickStub.callCount === 5);
|
||||
should(quickpickStub.getCall(4).args).deepEqual([
|
||||
[constants.connectionProfile, constants.userConnectionString],
|
||||
{
|
||||
canPickMany: false,
|
||||
ignoreFocusOut: true,
|
||||
title: constants.selectConnectionString
|
||||
}]);
|
||||
});
|
||||
});
|
||||
@@ -1,62 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
import * as should from 'should';
|
||||
import * as os from 'os';
|
||||
import * as vscode from 'vscode';
|
||||
import * as sinon from 'sinon';
|
||||
import * as constants from '../common/constants';
|
||||
import * as azureFunctionUtils from '../common/azureFunctionsUtils';
|
||||
import { PackageHelper } from '../tools/packageHelper';
|
||||
import { createContext, TestContext } from './testContext';
|
||||
|
||||
let testContext: TestContext;
|
||||
let packageHelper: PackageHelper;
|
||||
|
||||
describe('PackageHelper tests', function (): void {
|
||||
beforeEach(function (): void {
|
||||
testContext = createContext();
|
||||
packageHelper = new PackageHelper(testContext.outputChannel);
|
||||
});
|
||||
|
||||
afterEach(function (): void {
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
it('Should construct correct add Package Arguments', function (): void {
|
||||
const packageHelper = new PackageHelper( vscode.window.createOutputChannel('db project test'));
|
||||
const projectUri = vscode.Uri.file('dummy\\project\\path.csproj');
|
||||
const result = packageHelper.constructAddPackageArguments(projectUri, constants.sqlExtensionPackageName);
|
||||
|
||||
if (os.platform() === 'win32') {
|
||||
should(result).equal(` add "\\\\dummy\\\\project\\\\path.csproj" package ${constants.sqlExtensionPackageName} --prerelease`);
|
||||
}
|
||||
else {
|
||||
should(result).equal(` add "/dummy/project/path.csproj" package ${constants.sqlExtensionPackageName} --prerelease`);
|
||||
}
|
||||
});
|
||||
|
||||
it('Should construct correct add Package Arguments with version', function (): void {
|
||||
const packageHelper = new PackageHelper( vscode.window.createOutputChannel('db project test'));
|
||||
const projectUri = vscode.Uri.file('dummy\\project\\path.csproj');
|
||||
const result = packageHelper.constructAddPackageArguments(projectUri, constants.sqlExtensionPackageName, constants.VersionNumber);
|
||||
|
||||
if (os.platform() === 'win32') {
|
||||
should(result).equal(` add "\\\\dummy\\\\project\\\\path.csproj" package ${constants.sqlExtensionPackageName} -v ${constants.VersionNumber}`);
|
||||
}
|
||||
else {
|
||||
should(result).equal(` add "/dummy/project/path.csproj" package ${constants.sqlExtensionPackageName} -v ${constants.VersionNumber}`);
|
||||
}
|
||||
});
|
||||
|
||||
it('Should show info message to add sql bindings package if project is not found', async function (): Promise<void> {
|
||||
sinon.stub(azureFunctionUtils, 'getAFProjectContainingFile').resolves(undefined);
|
||||
const spy = sinon.spy(vscode.window, 'showInformationMessage');
|
||||
|
||||
await packageHelper.addPackageToAFProjectContainingFile(vscode.Uri.file(''), constants.sqlExtensionPackageName);
|
||||
should(spy.calledOnce).be.true('showInformationMessage should have been called exactly once');
|
||||
});
|
||||
});
|
||||
@@ -8,16 +8,11 @@ import * as azdata from 'azdata';
|
||||
import * as path from 'path';
|
||||
import * as TypeMoq from 'typemoq';
|
||||
import * as mssql from '../../../mssql/src/mssql';
|
||||
import * as vscodeMssql from 'vscode-mssql';
|
||||
|
||||
export interface TestContext {
|
||||
context: vscode.ExtensionContext;
|
||||
dacFxService: TypeMoq.IMock<mssql.IDacFxService>;
|
||||
azureFunctionService: TypeMoq.IMock<vscodeMssql.IAzureFunctionsService>;
|
||||
outputChannel: vscode.OutputChannel;
|
||||
vscodeMssqlIExtension: TypeMoq.IMock<vscodeMssql.IExtension>
|
||||
dacFxMssqlService: TypeMoq.IMock<vscodeMssql.IDacFxService>;
|
||||
schemaCompareService: TypeMoq.IMock<vscodeMssql.ISchemaCompareService>;
|
||||
}
|
||||
|
||||
export const mockDacFxResult = {
|
||||
@@ -124,153 +119,6 @@ export class MockDacFxService implements mssql.IDacFxService {
|
||||
public validateStreamingJob(_: string, __: string): Thenable<mssql.ValidateStreamingJobResult> { return Promise.resolve(mockDacFxResult); }
|
||||
}
|
||||
|
||||
export const mockResultStatus = {
|
||||
success: true,
|
||||
errorMessage: ''
|
||||
};
|
||||
|
||||
export const mockGetAzureFunctionsResult = {
|
||||
success: true,
|
||||
errorMessage: '',
|
||||
azureFunctions: []
|
||||
};
|
||||
|
||||
export class MockAzureFunctionService implements vscodeMssql.IAzureFunctionsService {
|
||||
addSqlBinding(_: vscodeMssql.BindingType, __: string, ___: string, ____: string, _____: string): Thenable<vscodeMssql.ResultStatus> { return Promise.resolve(mockResultStatus); }
|
||||
getAzureFunctions(_: string): Thenable<vscodeMssql.GetAzureFunctionsResult> { return Promise.resolve(mockGetAzureFunctionsResult); }
|
||||
}
|
||||
|
||||
export const mockDacFxMssqlOptionResult: vscodeMssql.DacFxOptionsResult = {
|
||||
success: true,
|
||||
errorMessage: '',
|
||||
deploymentOptions: {
|
||||
ignoreTableOptions: false,
|
||||
ignoreSemicolonBetweenStatements: false,
|
||||
ignoreRouteLifetime: false,
|
||||
ignoreRoleMembership: false,
|
||||
ignoreQuotedIdentifiers: false,
|
||||
ignorePermissions: false,
|
||||
ignorePartitionSchemes: false,
|
||||
ignoreObjectPlacementOnPartitionScheme: false,
|
||||
ignoreNotForReplication: false,
|
||||
ignoreLoginSids: false,
|
||||
ignoreLockHintsOnIndexes: false,
|
||||
ignoreKeywordCasing: false,
|
||||
ignoreIndexPadding: false,
|
||||
ignoreIndexOptions: false,
|
||||
ignoreIncrement: false,
|
||||
ignoreIdentitySeed: false,
|
||||
ignoreUserSettingsObjects: false,
|
||||
ignoreFullTextCatalogFilePath: false,
|
||||
ignoreWhitespace: false,
|
||||
ignoreWithNocheckOnForeignKeys: false,
|
||||
verifyCollationCompatibility: false,
|
||||
unmodifiableObjectWarnings: false,
|
||||
treatVerificationErrorsAsWarnings: false,
|
||||
scriptRefreshModule: false,
|
||||
scriptNewConstraintValidation: false,
|
||||
scriptFileSize: false,
|
||||
scriptDeployStateChecks: false,
|
||||
scriptDatabaseOptions: false,
|
||||
scriptDatabaseCompatibility: false,
|
||||
scriptDatabaseCollation: false,
|
||||
runDeploymentPlanExecutors: false,
|
||||
registerDataTierApplication: false,
|
||||
populateFilesOnFileGroups: false,
|
||||
noAlterStatementsToChangeClrTypes: false,
|
||||
includeTransactionalScripts: false,
|
||||
includeCompositeObjects: false,
|
||||
allowUnsafeRowLevelSecurityDataMovement: false,
|
||||
ignoreWithNocheckOnCheckConstraints: false,
|
||||
ignoreFillFactor: false,
|
||||
ignoreFileSize: false,
|
||||
ignoreFilegroupPlacement: false,
|
||||
doNotAlterReplicatedObjects: false,
|
||||
doNotAlterChangeDataCaptureObjects: false,
|
||||
disableAndReenableDdlTriggers: false,
|
||||
deployDatabaseInSingleUserMode: false,
|
||||
createNewDatabase: false,
|
||||
compareUsingTargetCollation: false,
|
||||
commentOutSetVarDeclarations: false,
|
||||
blockWhenDriftDetected: false,
|
||||
blockOnPossibleDataLoss: false,
|
||||
backupDatabaseBeforeChanges: false,
|
||||
allowIncompatiblePlatform: false,
|
||||
allowDropBlockingAssemblies: false,
|
||||
dropConstraintsNotInSource: false,
|
||||
dropDmlTriggersNotInSource: false,
|
||||
dropExtendedPropertiesNotInSource: false,
|
||||
dropIndexesNotInSource: false,
|
||||
ignoreFileAndLogFilePath: false,
|
||||
ignoreExtendedProperties: false,
|
||||
ignoreDmlTriggerState: false,
|
||||
ignoreDmlTriggerOrder: false,
|
||||
ignoreDefaultSchema: false,
|
||||
ignoreDdlTriggerState: false,
|
||||
ignoreDdlTriggerOrder: false,
|
||||
ignoreCryptographicProviderFilePath: false,
|
||||
verifyDeployment: false,
|
||||
ignoreComments: false,
|
||||
ignoreColumnCollation: false,
|
||||
ignoreAuthorizer: false,
|
||||
ignoreAnsiNulls: false,
|
||||
generateSmartDefaults: false,
|
||||
dropStatisticsNotInSource: false,
|
||||
dropRoleMembersNotInSource: false,
|
||||
dropPermissionsNotInSource: false,
|
||||
dropObjectsNotInSource: false,
|
||||
ignoreColumnOrder: false,
|
||||
doNotDropObjectTypes: [],
|
||||
excludeObjectTypes: []
|
||||
}
|
||||
};
|
||||
|
||||
export class MockDacFxMssqlService implements vscodeMssql.IDacFxService {
|
||||
public exportBacpac(_: string, __: string, ___: string, ____: vscodeMssql.TaskExecutionMode): Thenable<vscodeMssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
||||
public importBacpac(_: string, __: string, ___: string, ____: vscodeMssql.TaskExecutionMode): Thenable<mssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
||||
public extractDacpac(_: string, __: string, ___: string, ____: string, _____: string, ______: vscodeMssql.TaskExecutionMode): Thenable<mssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
||||
public createProjectFromDatabase(_: string, __: string, ___: string, ____: string, _____: string, ______: vscodeMssql.ExtractTarget, _______: vscodeMssql.TaskExecutionMode): Thenable<vscodeMssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
||||
public deployDacpac(_: string, __: string, ___: boolean, ____: string, _____: vscodeMssql.TaskExecutionMode, ______?: Record<string, string>): Thenable<mssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
||||
public generateDeployScript(_: string, __: string, ___: string, ____: vscodeMssql.TaskExecutionMode, ______?: Record<string, string>): Thenable<mssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
||||
public generateDeployPlan(_: string, __: string, ___: string, ____: vscodeMssql.TaskExecutionMode): Thenable<vscodeMssql.GenerateDeployPlanResult> { return Promise.resolve(mockDacFxResult); }
|
||||
public getOptionsFromProfile(_: string): Thenable<vscodeMssql.DacFxOptionsResult> { return Promise.resolve(mockDacFxMssqlOptionResult); }
|
||||
public validateStreamingJob(_: string, __: string): Thenable<mssql.ValidateStreamingJobResult> { return Promise.resolve(mockDacFxResult); }
|
||||
}
|
||||
|
||||
export class MockSchemaCompareService implements vscodeMssql.ISchemaCompareService {
|
||||
schemaCompareGetDefaultOptions(): Thenable<vscodeMssql.SchemaCompareOptionsResult> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
|
||||
export class MockVscodeMssqlIExtension implements vscodeMssql.IExtension {
|
||||
sqlToolsServicePath: string = '';
|
||||
dacFx: vscodeMssql.IDacFxService;
|
||||
schemaCompare: vscodeMssql.ISchemaCompareService;
|
||||
azureFunctions: vscodeMssql.IAzureFunctionsService;
|
||||
|
||||
constructor() {
|
||||
this.dacFx = new MockDacFxMssqlService;
|
||||
this.schemaCompare = new MockSchemaCompareService;
|
||||
this.azureFunctions = new MockAzureFunctionService;
|
||||
}
|
||||
promptForConnection(_?: boolean): Promise<vscodeMssql.IConnectionInfo | undefined> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
connect(_: vscodeMssql.IConnectionInfo, __?: boolean): Promise<string> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
listDatabases(_: string): Promise<string[]> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
getDatabaseNameFromTreeNode(_: vscodeMssql.ITreeNodeInfo): string {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
getConnectionString(_: string | vscodeMssql.ConnectionDetails, ___?: boolean, _____?: boolean): Promise<string> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
|
||||
export function createContext(): TestContext {
|
||||
let extensionPath = path.join(__dirname, '..', '..');
|
||||
|
||||
@@ -303,10 +151,6 @@ export function createContext(): TestContext {
|
||||
extension: undefined as any
|
||||
},
|
||||
dacFxService: TypeMoq.Mock.ofType(MockDacFxService),
|
||||
azureFunctionService: TypeMoq.Mock.ofType(MockAzureFunctionService),
|
||||
vscodeMssqlIExtension: TypeMoq.Mock.ofType(MockVscodeMssqlIExtension),
|
||||
dacFxMssqlService: TypeMoq.Mock.ofType(MockDacFxMssqlService),
|
||||
schemaCompareService: TypeMoq.Mock.ofType(MockSchemaCompareService),
|
||||
outputChannel: {
|
||||
name: '',
|
||||
append: () => { },
|
||||
@@ -342,41 +186,3 @@ export const mockConnectionProfile: azdata.IConnectionProfile = {
|
||||
connectionName: 'My Connection Name'
|
||||
}
|
||||
};
|
||||
|
||||
export function createTestCredentials(): vscodeMssql.IConnectionInfo {
|
||||
const creds: vscodeMssql.IConnectionInfo = {
|
||||
server: 'my-server',
|
||||
database: 'my_db',
|
||||
user: 'sa',
|
||||
password: '12345678',
|
||||
email: 'test-email',
|
||||
accountId: 'test-account-id',
|
||||
port: 1234,
|
||||
authenticationType: 'test',
|
||||
azureAccountToken: '',
|
||||
expiresOn: 0,
|
||||
encrypt: false,
|
||||
trustServerCertificate: false,
|
||||
persistSecurityInfo: false,
|
||||
connectTimeout: 15,
|
||||
connectRetryCount: 0,
|
||||
connectRetryInterval: 0,
|
||||
applicationName: 'vscode-mssql',
|
||||
workstationId: 'test',
|
||||
applicationIntent: '',
|
||||
currentLanguage: '',
|
||||
pooling: true,
|
||||
maxPoolSize: 15,
|
||||
minPoolSize: 0,
|
||||
loadBalanceTimeout: 0,
|
||||
replication: false,
|
||||
attachDbFilename: '',
|
||||
failoverPartner: '',
|
||||
multiSubnetFailover: false,
|
||||
multipleActiveResultSets: false,
|
||||
packetSize: 8192,
|
||||
typeSystemVersion: 'Latest',
|
||||
connectionString: ''
|
||||
};
|
||||
return creds;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user