Add SQL Bindings Tests / Vbump (#19717)

* add further testing

* vbump version

* add successfully test

* address comments
This commit is contained in:
Vasu Bhog
2022-06-14 14:47:36 -07:00
committed by GitHub
parent ba82444229
commit 6ab09d9b1b
8 changed files with 384 additions and 70 deletions

View File

@@ -3,21 +3,21 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as fs from 'fs';
import * as should from 'should';
import * as sinon from 'sinon';
import * as vscode from 'vscode';
import * as TypeMoq from 'typemoq';
import * as fs from 'fs';
import * as utils from '../../common/utils';
import * as constants from '../../common/constants';
import * as vscode from 'vscode';
import * as azureFunctionUtils from '../../common/azureFunctionsUtils';
import * as azureFunctionService from '../../services/azureFunctionsService';
import * as constants from '../../common/constants';
import * as utils from '../../common/utils';
import * as azureFunctionsContracts from '../../contracts/azureFunctions/azureFunctionsContracts';
import * as azureFunctionService from '../../services/azureFunctionsService';
import { createTestUtils, TestUtils, createTestCredentials } from '../testUtils';
import { launchAddSqlBindingQuickpick } from '../../dialogs/addSqlBindingQuickpick';
import { BindingType } from 'sql-bindings';
import { IConnectionInfo } from 'vscode-mssql';
import { launchAddSqlBindingQuickpick } from '../../dialogs/addSqlBindingQuickpick';
import { createTestCredentials, createTestUtils, TestUtils } from '../testUtils';
let testUtils: TestUtils;
const fileUri = vscode.Uri.file('testUri');
@@ -30,30 +30,13 @@ describe('Add SQL Binding quick pick', () => {
sinon.restore();
});
it('Should show error if the file contains no Azure Functions', async function (): Promise<void> {
sinon.stub(utils, 'getVscodeMssqlApi').resolves(testUtils.vscodeMssqlIExtension.object);
sinon.stub(azureFunctionService, 'getAzureFunctions').withArgs(fileUri.fsPath).returns(
Promise.resolve({
success: true,
errorMessage: '',
azureFunctions: []
}));
const spy = sinon.spy(vscode.window, 'showErrorMessage');
await launchAddSqlBindingQuickpick(fileUri);
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> {
it('Should successfully add SQL binding', async function (): Promise<void> {
sinon.stub(utils, 'getVscodeMssqlApi').resolves(testUtils.vscodeMssqlIExtension.object);
let connectionCreds: IConnectionInfo = createTestCredentials();// Mocks promptForConnection
let connectionDetails = { options: connectionCreds };
// set test vscode-mssql API calls
testUtils.vscodeMssqlIExtension.setup(x => x.promptForConnection(true)).returns(() => Promise.resolve(connectionCreds));
testUtils.vscodeMssqlIExtension.setup(x => x.getConnectionString(connectionDetails, true, false)).returns(() => Promise.resolve('testConnectionString'));
testUtils.vscodeMssqlIExtension.setup(x => x.getConnectionString(connectionDetails, true, false)).returns(() => Promise.resolve('testConnectionString1'));
testUtils.vscodeMssqlIExtension.setup(x => x.connect(connectionCreds)).returns(() => Promise.resolve('testConnectionURI'));
testUtils.vscodeMssqlIExtension.setup(x => x.listDatabases('testConnectionURI')).returns(() => Promise.resolve(['testDb']));
const params = { ownerUri: 'testConnectionURI', queryString: azureFunctionUtils.tablesQuery('testDb') };
@@ -66,17 +49,15 @@ describe('Add SQL Binding quick pick', () => {
errorMessage: '',
azureFunctions: ['af1', 'af2']
}));
//failure since no AFs are found in the project
const errormsg = 'Error inserting binding';
sinon.stub(azureFunctionService, 'addSqlBinding').withArgs(
sinon.match.any, sinon.match.any, sinon.match.any,
sinon.match.any, sinon.match.any).returns(
Promise.resolve({
success: false,
errorMessage: errormsg
success: true,
errorMessage: ''
}));
const spy = sinon.spy(vscode.window, 'showErrorMessage');
const showErrorMessageSpy = sinon.spy(vscode.window, 'showErrorMessage');
// select Azure function
let quickpickStub = sinon.stub(vscode.window, 'showQuickPick').returns(Promise.resolve('af1') as any);
@@ -91,18 +72,88 @@ describe('Add SQL Binding quick pick', () => {
quickpickStub.onCall(4).returns(Promise.resolve(constants.yesString) as any);
// setLocalAppSetting fails if we dont set writeFile stub
sinon.stub(fs.promises, 'writeFile');
sinon.stub(azureFunctionUtils, 'setLocalAppSetting').withArgs(sinon.match.any, 'sqlConnectionString', 'testConnectionString').returns(Promise.resolve(true));
sinon.stub(azureFunctionUtils, 'setLocalAppSetting').withArgs(sinon.match.any, 'sqlConnectionString', 'testConnectionString1').returns(Promise.resolve(true));
sinon.stub(utils, 'executeCommand').resolves('downloaded nuget package');
quickpickStub.onCall(5).returns(Promise.resolve('testDb') as any);
quickpickStub.onCall(6).returns(Promise.resolve('[schema].[testTable]') as any);
await launchAddSqlBindingQuickpick(vscode.Uri.file('testUri'));
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]}'`);
should(showErrorMessageSpy.notCalled).be.true('showErrorMessage should not be called');
});
it('Should show error connection profile does not connect', async function (): Promise<void> {
it('Should show error if adding SQL binding was not successful', async function (): Promise<void> {
sinon.stub(utils, 'getVscodeMssqlApi').resolves(testUtils.vscodeMssqlIExtension.object);
let connectionCreds: IConnectionInfo = createTestCredentials();// Mocks promptForConnection
let connectionDetails = { options: connectionCreds };
// set test vscode-mssql API calls
testUtils.vscodeMssqlIExtension.setup(x => x.promptForConnection(true)).returns(() => Promise.resolve(connectionCreds));
testUtils.vscodeMssqlIExtension.setup(x => x.getConnectionString(connectionDetails, true, false)).returns(() => Promise.resolve('testConnectionString2'));
testUtils.vscodeMssqlIExtension.setup(x => x.connect(connectionCreds)).returns(() => Promise.resolve('testConnectionURI'));
testUtils.vscodeMssqlIExtension.setup(x => x.listDatabases('testConnectionURI')).returns(() => Promise.resolve(['testDb']));
const params = { ownerUri: 'testConnectionURI', queryString: azureFunctionUtils.tablesQuery('testDb') };
testUtils.vscodeMssqlIExtension.setup(x => x.sendRequest(azureFunctionsContracts.SimpleExecuteRequest.type, params))
.returns(() => Promise.resolve({ rowCount: 1, columnInfo: [], rows: [['[schema].[testTable]']] }));
sinon.stub(azureFunctionService, 'getAzureFunctions').withArgs(fileUri.fsPath).returns(
Promise.resolve({
success: true,
errorMessage: '',
azureFunctions: ['af1', 'af2']
}));
//failure since no AFs are found in the project
const errormsg = 'Error inserting binding';
sinon.stub(azureFunctionService, 'addSqlBinding').withArgs(
sinon.match.any, sinon.match.any, sinon.match.any,
sinon.match.any, sinon.match.any).returns(
Promise.resolve({
success: false,
errorMessage: errormsg
}));
const showErrorMessageSpy = sinon.spy(vscode.window, 'showErrorMessage');
// select Azure function
let quickpickStub = sinon.stub(vscode.window, 'showQuickPick').returns(Promise.resolve('af1') as any);
// select input or output binding
quickpickStub.onSecondCall().resolves(<any>{ label: constants.input, type: BindingType.input });
sinon.stub(azureFunctionUtils, 'getAFProjectContainingFile').resolves(vscode.Uri.file('testUri'));
// select connection profile - create new
quickpickStub.onThirdCall().resolves(<any>{ label: constants.createNewLocalAppSettingWithIcon });
// give connection string setting name
sinon.stub(vscode.window, 'showInputBox').onFirstCall().resolves('sqlConnectionString');
quickpickStub.onCall(3).returns(Promise.resolve(constants.connectionProfile) as any);
quickpickStub.onCall(4).returns(Promise.resolve(constants.yesString) as any);
// setLocalAppSetting fails if we dont set writeFile stub
sinon.stub(fs.promises, 'writeFile');
sinon.stub(azureFunctionUtils, 'setLocalAppSetting').withArgs(sinon.match.any, 'sqlConnectionString', 'testConnectionString2').returns(Promise.resolve(true));
sinon.stub(utils, 'executeCommand').resolves('downloaded nuget package');
quickpickStub.onCall(5).returns(Promise.resolve('testDb') as any);
quickpickStub.onCall(6).returns(Promise.resolve('[schema].[testTable]') as any);
await launchAddSqlBindingQuickpick(vscode.Uri.file('testUri'));
should(showErrorMessageSpy.calledOnce).be.true('showErrorMessage should have been called exactly once');
should(showErrorMessageSpy.calledWith(errormsg)).be.true(`showErrorMessage not called with expected message '${errormsg}' Actual '${showErrorMessageSpy.getCall(0).args[0]}'`);
});
it('Should show error if the file contains no Azure Functions', async function (): Promise<void> {
sinon.stub(utils, 'getVscodeMssqlApi').resolves(testUtils.vscodeMssqlIExtension.object);
sinon.stub(azureFunctionService, 'getAzureFunctions').withArgs(fileUri.fsPath).returns(
Promise.resolve({
success: true,
errorMessage: '',
azureFunctions: []
}));
const showErrorMessageSpy = sinon.spy(vscode.window, 'showErrorMessage');
await launchAddSqlBindingQuickpick(fileUri);
const msg = constants.noAzureFunctionsInFile;
should(showErrorMessageSpy.calledOnce).be.true('showErrorMessage should have been called exactly once');
should(showErrorMessageSpy.calledWith(msg)).be.true(`showErrorMessage not called with expected message '${msg}' Actual '${showErrorMessageSpy.getCall(0).args[0]}'`);
});
it('Should show error when connection profile does not connect', async function (): Promise<void> {
sinon.stub(utils, 'getVscodeMssqlApi').resolves(testUtils.vscodeMssqlIExtension.object);
let connectionCreds = createTestCredentials();
@@ -114,40 +165,116 @@ describe('Add SQL Binding quick pick', () => {
azureFunctions: ['af1']
}));
// Mocks connect call to mssql
let error = new Error('Connection Request Failed');
testUtils.vscodeMssqlIExtension.setup(x => x.connect(TypeMoq.It.isAny(), undefined)).throws(error);
// Mocks promptForConnection
testUtils.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(<any>{ label: constants.input, type: BindingType.input });
// give object name
let inputBoxStub = sinon.stub(vscode.window, 'showInputBox').onFirstCall().resolves('dbo.table1');
// select connection string setting name
quickpickStub.onThirdCall().resolves({ label: constants.createNewLocalAppSettingWithIcon });
// give connection string setting name
inputBoxStub.onSecondCall().resolves('SqlConnectionString');
sinon.stub(vscode.window, 'showInputBox').onFirstCall().resolves('SqlConnectionString');
// select connection profile method
quickpickStub.onCall(3).resolves({ label: constants.connectionProfile });
testUtils.vscodeMssqlIExtension.setup(x => x.promptForConnection(true)).returns(() => Promise.resolve(connectionCreds));
// Mocks connect call to mssql
let error = new Error('Connection Request Failed');
testUtils.vscodeMssqlIExtension.setup(x => x.connect(TypeMoq.It.isAny(), undefined)).throws(error);
await launchAddSqlBindingQuickpick(vscode.Uri.file('testUri'));
// should go back to the select connection string methods
should(quickpickStub.callCount === 4);
should(quickpickStub.callCount).be.equal(5,'showQuickPick should have been called 5 times');
should(quickpickStub.getCall(3).args).deepEqual([
[constants.connectionProfile, constants.userConnectionString],
{
canPickMany: false,
ignoreFocusOut: true,
title: constants.selectConnectionString
}]);
}]
);
});
it('Should show user connection string setting method after cancelling out of connection string setting name', async function (): Promise<void> {
sinon.stub(azureFunctionUtils, 'getAFProjectContainingFile').resolves(vscode.Uri.file('testUri'));
sinon.stub(azureFunctionService, 'getAzureFunctions').withArgs(fileUri.fsPath).returns(
Promise.resolve({
success: true,
errorMessage: '',
azureFunctions: ['af1']
}));
// Mocks promptForConnection
let quickpickStub = sinon.stub(vscode.window, 'showQuickPick');
// select Azure function
quickpickStub.onFirstCall().resolves({ label: 'af1' });
// select input or output binding
quickpickStub.onSecondCall().resolves(<any>{ label: constants.input, type: BindingType.input });
// select connection string setting name
quickpickStub.onThirdCall().resolves({ label: constants.createNewLocalAppSettingWithIcon });
// give connection string setting name
sinon.stub(vscode.window, 'showInputBox').onFirstCall().resolves(undefined);
await launchAddSqlBindingQuickpick(vscode.Uri.file('testUri'));
// should go back to the select connection string methods
should(quickpickStub.callCount).be.equal(4,'showQuickPick should have been called 4 times');
should(quickpickStub.getCall(2).args).containDeepOrdered([
[{ label: constants.createNewLocalAppSettingWithIcon }],
{
canPickMany: false,
title: constants.selectSetting,
ignoreFocusOut: true
}]
);
});
it('Should show user connection string setting method after cancelling out of manually entering connection string', async function (): Promise<void> {
sinon.stub(azureFunctionUtils, 'getAFProjectContainingFile').resolves(vscode.Uri.file('testUri'));
sinon.stub(azureFunctionService, 'getAzureFunctions').withArgs(fileUri.fsPath).returns(
Promise.resolve({
success: true,
errorMessage: '',
azureFunctions: ['af1']
}));
// Mocks promptForConnection
let quickpickStub = sinon.stub(vscode.window, 'showQuickPick');
// select Azure function
quickpickStub.onFirstCall().resolves({ label: 'af1' });
// select input or output binding
quickpickStub.onSecondCall().resolves(<any>{ label: constants.input, type: BindingType.input });
// select connection string setting name
quickpickStub.onThirdCall().resolves({ label: constants.createNewLocalAppSettingWithIcon });
// give connection string setting name
let inputBox = sinon.stub(vscode.window, 'showInputBox').onFirstCall().resolves('SqlConnectionString');
// select enter connection string manually
quickpickStub.onCall(3).resolves({ label: constants.enterConnectionString });
// user cancels prompt to enter connection string
inputBox.onSecondCall().resolves(undefined);
await launchAddSqlBindingQuickpick(vscode.Uri.file('testUri'));
// should go back to the select connection string methods
should(quickpickStub.callCount).be.equal(5,'showQuickPick should have been called 5 times');
should(quickpickStub.getCall(4).args).containDeepOrdered([
[constants.connectionProfile, constants.enterConnectionString],
{
canPickMany: false,
title: constants.selectConnectionString,
ignoreFocusOut: true
}]
);
});
});