[SQL Bindings] Skip prompt to select setting from connection settings if there is none (#19798)

* add no setting option

* add tests

* reformat tests
This commit is contained in:
Vasu Bhog
2022-06-27 12:31:46 -07:00
committed by GitHub
parent fae67b4485
commit d5da934572
5 changed files with 455 additions and 113 deletions

View File

@@ -26,36 +26,27 @@ describe('AzureFunctionUtils', function (): void {
});
describe('Local.Settings.Json', function (): void {
it('Should correctly parse local.settings.json', async () => {
beforeEach(function (): void {
// create fake connection string settings for local.setting.json to be used
sinon.stub(fs.promises, 'access').onFirstCall().resolves();
sinon.stub(fs, 'readFileSync').withArgs(localSettingsPath).returns(
`{"IsEncrypted": false,
"Values": {"test1": "test1", "test2": "test2", "test3":"test3"}}`
"Values": {"test1": "test1", "test2": "test2", "test3":"test3"}}`
);
});
it('Should correctly parse local.settings.json', async () => {
let settings = await azureFunctionsUtils.getLocalSettingsJson(localSettingsPath);
should(settings.IsEncrypted).equals(false);
should(Object.keys(settings.Values!).length).equals(3);
});
it('setLocalAppSetting can update settings.json with new setting value', async () => {
sinon.stub(fs.promises, 'access').onFirstCall().resolves();
sinon.stub(fs, 'readFileSync').withArgs(localSettingsPath).returns(
`{"IsEncrypted": false,
"Values": {"test1": "test1", "test2": "test2", "test3":"test3"}}`
);
let writeFileStub = sinon.stub(fs.promises, 'writeFile').resolves();
await azureFunctionsUtils.setLocalAppSetting(path.dirname(localSettingsPath), 'test4', 'test4');
should(writeFileStub.calledWithExactly(localSettingsPath, `{\n "IsEncrypted": false,\n "Values": {\n "test1": "test1",\n "test2": "test2",\n "test3": "test3",\n "test4": "test4"\n }\n}`)).equals(true, 'writeFile should be called with the correct arguments');
});
it('Should not overwrite setting if value already exists in local.settings.json', async () => {
sinon.stub(fs.promises, 'access').onFirstCall().resolves();
sinon.stub(fs, 'readFileSync').withArgs(localSettingsPath).returns(
`{"IsEncrypted": false,
"Values": {"test1": "test1", "test2": "test2", "test3":"test3"}}`
);
let warningMsg = constants.settingAlreadyExists('test1');
const showErrorMessageSpy = sinon.stub(vscode.window, 'showWarningMessage').resolves({ title: constants.settingAlreadyExists('test1') });
@@ -70,11 +61,6 @@ describe('AzureFunctionUtils', function (): void {
});
it('Should add connection string to local.settings.json', async () => {
sinon.stub(fs.promises, 'access').onFirstCall().resolves();
sinon.stub(fs, 'readFileSync').withArgs(localSettingsPath).returns(
`{"IsEncrypted": false,
"Values": {"test1": "test1", "test2": "test2", "test3":"test3"}}`
);
const connectionString = 'testConnectionString';
let writeFileStub = sinon.stub(fs.promises, 'writeFile').resolves();
@@ -84,6 +70,14 @@ describe('AzureFunctionUtils', function (): void {
});
describe('Password Prompts', function (): void {
beforeEach(function (): void {
sinon.stub(fs.promises, 'access').onFirstCall().resolves();
sinon.stub(fs, 'readFileSync').withArgs(localSettingsPath).returns(
`{"IsEncrypted": false,
"Values": {"test1": "test1", "test2": "test2", "test3":"test3"}}`
);
});
it('Should include password if user includes password and connection info contains the password and auth type is SQL', async () => {
sinon.stub(utils, 'getVscodeMssqlApi').resolves(testUtils.vscodeMssqlIExtension.object);
let connectionInfo: IConnectionInfo = createTestCredentials();// Mocks promptForConnection
@@ -106,7 +100,7 @@ describe('AzureFunctionUtils', function (): void {
should(quickInputSpy.notCalled).be.true('showInputBox should not have been called');
should(warningSpy.notCalled).be.true('showWarningMessage should not have been called');
// get connection string result
should(getConnectionString).equals(`Server=${connectionInfo.server};Initial Catalog=${connectionInfo.database};User ID=${connectionInfo.user};Password=${connectionInfo.password};`,'Should return a connection string with the password');
should(getConnectionString).equals(`Server=${connectionInfo.server};Initial Catalog=${connectionInfo.database};User ID=${connectionInfo.user};Password=${connectionInfo.password};`, 'Should return a connection string with the password');
});
it('Should not include password and show warning if user does not want to include password prompt and connection info contains the password and auth type is SQL', async () => {
@@ -131,7 +125,7 @@ describe('AzureFunctionUtils', function (): void {
should(quickInputSpy.notCalled).be.true('showInputBox should not have been called');
should(warningSpy.calledOnce).be.true('showWarningMessage should have been called');
// returned connection string should NOT include password
should(getConnectionString).equals(`Server=${connectionInfo.server};Initial Catalog=${connectionInfo.database};User ID=${connectionInfo.user};Password=${constants.passwordPlaceholder};`,'Should return a connection string without the password');
should(getConnectionString).equals(`Server=${connectionInfo.server};Initial Catalog=${connectionInfo.database};User ID=${connectionInfo.user};Password=${constants.passwordPlaceholder};`, 'Should return a connection string without the password');
});
it('Should not include password and show warning if user cancels include password prompt and connection info contains the password and auth type is SQL', async () => {
@@ -301,40 +295,40 @@ describe('AzureFunctionUtils', function (): void {
describe('PromptForObjectName', function (): void {
it('Should prompt user to enter object name manually when no connection info given', async () => {
let promptStub = sinon.stub(vscode.window, 'showInputBox').onFirstCall().resolves('test');
let inputBoxStub = sinon.stub(vscode.window, 'showInputBox').onFirstCall().resolves('test');
let result = await azureFunctionsUtils.promptForObjectName(BindingType.input);
should(promptStub.calledOnce).be.true('showInputBox should have been called');
should(inputBoxStub.calledOnce).be.true('showInputBox should have been called');
should(result).be.equal('test', 'Should return test since user manually entered object name');
});
it('Should return undefined when mssql connection error', async () => {
sinon.stub(utils, 'getVscodeMssqlApi').resolves(testUtils.vscodeMssqlIExtension.object);
let connectionInfo: IConnectionInfo = createTestCredentials();// Mocks promptForConnection
let promptStub = sinon.stub(vscode.window, 'showInputBox');
let inputBoxStub = sinon.stub(vscode.window, 'showInputBox');
sinon.stub(azureFunctionsUtils, 'getConnectionURI').resolves(undefined);
let result = await azureFunctionsUtils.promptForObjectName(BindingType.input, connectionInfo);
should(promptStub.notCalled).be.true('showInputBox should not have been called');
should(inputBoxStub.notCalled).be.true('showInputBox should not have been called');
should(result).be.equal(undefined, 'Should return undefined due to mssql connection error');
});
it('Should return undefined if no database selected', async () => {
sinon.stub(utils, 'getVscodeMssqlApi').resolves(testUtils.vscodeMssqlIExtension.object);
let connectionInfo: IConnectionInfo = createTestCredentials();// Mocks promptForConnection
let promptStub = sinon.stub(vscode.window, 'showInputBox');
let inputBoxStub = sinon.stub(vscode.window, 'showInputBox');
testUtils.vscodeMssqlIExtension.setup(x => x.connect(connectionInfo)).returns(() => Promise.resolve('testConnectionURI'));
sinon.stub(vscode.window, 'showQuickPick').resolves(undefined);
let result = await azureFunctionsUtils.promptForObjectName(BindingType.input, connectionInfo);
should(promptStub.notCalled).be.true('showInputBox should not have been called');
should(inputBoxStub.notCalled).be.true('showInputBox should not have been called');
should(result).be.equal(undefined, 'Should return undefined due to no database selected');
});
it('Should successfully select object name', async () => {
sinon.stub(utils, 'getVscodeMssqlApi').resolves(testUtils.vscodeMssqlIExtension.object);
let connectionInfo: IConnectionInfo = createTestCredentials();// Mocks promptForConnection
let promptStub = sinon.stub(vscode.window, 'showInputBox');
let inputBoxStub = sinon.stub(vscode.window, 'showInputBox');
// getConnectionURI stub
testUtils.vscodeMssqlIExtension.setup(x => x.connect(connectionInfo)).returns(() => Promise.resolve('testConnectionURI'));
// promptSelectDatabase stub
@@ -349,13 +343,328 @@ describe('AzureFunctionUtils', function (): void {
let result = await azureFunctionsUtils.promptForObjectName(BindingType.input, connectionInfo);
should(promptStub.notCalled).be.true('showInputBox should not have been called');
should(inputBoxStub.notCalled).be.true('showInputBox should not have been called');
should(quickPickStub.calledTwice).be.true('showQuickPick should have been called twice');
should(connectionInfo.database).be.equal('testDb', 'Should have connectionInfo.database to testDb after user selects database');
should(result).be.equal('[schema].[testTable]', 'Should return [schema].[testTable] since user selected table');
});
});
describe('PromptAndUpdateConnectionStringSetting', function (): void {
const fileUri = vscode.Uri.file(path.join(rootFolderPath, 'testProjectU'));
it('Should prompt user to enter connection string setting only if no azure function project uri given', async () => {
let quickPickStub = sinon.spy(vscode.window, 'showQuickPick');
let inputBoxStub = sinon.stub(vscode.window, 'showInputBox').onFirstCall().resolves('test');
let result = await azureFunctionsUtils.promptAndUpdateConnectionStringSetting(undefined);
should(quickPickStub.notCalled).be.true('quickPickStub should not have been called');
should(inputBoxStub.calledOnce).be.true('showInputBox should have been called');
should(result?.connectionStringSettingName).be.equal('test', 'Should return test since user manually entered connection string');
should(inputBoxStub.firstCall.args).containEql(
{
prompt: constants.connectionStringSetting,
placeHolder: constants.connectionStringSettingPlaceholder,
ignoreFocusOut: true
}
);
});
describe('No local.settings.json file', function (): void {
let fileAccessStub: sinon.SinonStub;
beforeEach(function (): void {
// stubs for getLocalSettingsJson calls
// returns {IsEncrypted: False}
fileAccessStub = sinon.stub(fs.promises, 'access').onFirstCall().rejects();
});
it('Should prompt user to enter connection string setting name no connection info given', async () => {
let inputBoxStub = sinon.stub(vscode.window, 'showInputBox').onFirstCall().resolves('testConnectionStringName'); // enter connection string setting name
// no connection info given so prompt for connection info stubs
let quickPickStub = sinon.stub(vscode.window, 'showQuickPick').onFirstCall().resolves((constants.connectionProfile) as any);
sinon.stub(utils, 'getVscodeMssqlApi').resolves(testUtils.vscodeMssqlIExtension.object);
testUtils.vscodeMssqlIExtension.setup(x => x.promptForConnection(true)).returns(() => Promise.resolve(connectionInfo));
// passsword prompt stub
quickPickStub.onSecondCall().resolves((constants.yesString) as any);
// getConnectionString stubs - in password prompt logic
let connectionInfo: IConnectionInfo = createTestCredentials(); // create test connectionInfo
let connectionDetails = { options: connectionInfo };
testUtils.vscodeMssqlIExtension.setup(x => x.getConnectionString(connectionDetails, true, false)).returns(() => Promise.resolve('testConnectionString'));
// setLocalAppSetting stubs
fileAccessStub.onSecondCall().rejects(); // getLocalSettingsJson stub
// fails if we dont set writeFile stub
sinon.stub(fs.promises, 'writeFile').resolves();
sinon.stub(azureFunctionsUtils, 'setLocalAppSetting').withArgs(sinon.match.any, 'testConnectionStringName', 'testConnectionString').resolves((true));
// addSqlNugetReferenceToProjectFile stub
sinon.stub(utils, 'executeCommand').resolves('downloaded nuget package');
let result = await azureFunctionsUtils.promptAndUpdateConnectionStringSetting(fileUri);
should(inputBoxStub.calledOnce).be.true('showInputBox should have been called');
should(quickPickStub.callCount).be.equal(2, 'quickPickStub should have been called');
should(result?.connectionStringSettingName).be.equal('testConnectionStringName', 'Should return testConnectionStringName from manually entered connection string name');
});
it('Should prompt user to enter connection string setting name when connection info given', async () => {
let inputBoxStub = sinon.stub(vscode.window, 'showInputBox').onFirstCall().resolves('testConnectionStringName'); // enter connection string setting name
// password prompt stub
sinon.stub(utils, 'getVscodeMssqlApi').resolves(testUtils.vscodeMssqlIExtension.object);
let quickPickStub = sinon.stub(vscode.window, 'showQuickPick').onFirstCall().resolves((constants.yesString) as any);
// getConnectionString stubs - in password prompt logic
let connectionInfo: IConnectionInfo = createTestCredentials(); // create test connectionInfo
let connectionDetails = { options: connectionInfo };
testUtils.vscodeMssqlIExtension.setup(x => x.getConnectionString(connectionDetails, true, false)).returns(() => Promise.resolve('testConnectionString'));
// setLocalAppSetting stubs
fileAccessStub.onSecondCall().rejects(); // getLocalSettingsJson stub
// fails if we dont set writeFile stub
sinon.stub(fs.promises, 'writeFile').resolves();
sinon.stub(azureFunctionsUtils, 'setLocalAppSetting').withArgs(sinon.match.any, 'testConnectionStringName', 'testConnectionString').resolves((true));
// addSqlNugetReferenceToProjectFile stub
sinon.stub(utils, 'executeCommand').resolves('downloaded nuget package');
let result = await azureFunctionsUtils.promptAndUpdateConnectionStringSetting(fileUri, connectionInfo);
should(inputBoxStub.calledOnce).be.true('showInputBox should have been called');
should(quickPickStub.callCount).be.equal(1, 'quickPickStub should have been called');
should(result?.connectionStringSettingName).be.equal('testConnectionStringName', 'Should return testConnectionStringName from manually entered connection string name');
should(result?.connectionInfo).be.equal(connectionInfo, 'Should return connectionInfo');
});
it('Should return when user cancels out of manually entering connection string name prompt and has no existing connection string in local.settings.json', async () => {
let inputBoxStub = sinon.stub(vscode.window, 'showInputBox').onFirstCall().resolves(undefined); // user cancels out of connection string setting name
let quickPickSpy = sinon.spy(vscode.window, 'showQuickPick');
let result = await azureFunctionsUtils.promptAndUpdateConnectionStringSetting(fileUri);
should(inputBoxStub.calledOnce).be.true('showInputBox should have been called');
should(quickPickSpy.callCount).be.equal(0, 'quickPickStub should have been called');
should(result?.connectionStringSettingName).be.equal(undefined, 'Should return undefined since user cancelled out of connection string setting name prompt');
});
});
describe('local.settings.json file contains non-filtered connection setting tests', function (): void {
beforeEach(function (): void {
// create fake connection string settings for local.setting.json to be used
// getLocalSettingsJson stub
sinon.stub(fs.promises, 'access').resolves();
sinon.stub(fs, 'readFileSync').withArgs(sinon.match.any).returns(
`{"IsEncrypted": false,
"Values": {"test1": "test1", "test2": "test2", "test3":"test3"}}`
);
});
it('Should use user entered connection string setting name when non-filtered connection strings local.settings.json', async () => {
let quickPickStub = sinon.stub(vscode.window, 'showQuickPick').onFirstCall().resolves({ label: constants.createNewLocalAppSettingWithIcon }); // user chooses to create new connection string setting name
let inputBoxStub = sinon.stub(vscode.window, 'showInputBox').onFirstCall().resolves('testConnectionStringName'); // enter connection string setting name
// password prompt stub
sinon.stub(utils, 'getVscodeMssqlApi').resolves(testUtils.vscodeMssqlIExtension.object);
quickPickStub.onSecondCall().resolves((constants.yesString) as any);
// getConnectionString stubs - in password prompt logic
let connectionInfo: IConnectionInfo = createTestCredentials(); // create test connectionInfo
let connectionDetails = { options: connectionInfo };
testUtils.vscodeMssqlIExtension.setup(x => x.getConnectionString(connectionDetails, true, false)).returns(() => Promise.resolve('testConnectionString'));
// fails if we dont set writeFile stub
sinon.stub(fs.promises, 'writeFile').resolves();
sinon.stub(azureFunctionsUtils, 'setLocalAppSetting').withArgs(sinon.match.any, 'testConnectionStringName', 'testConnectionString').resolves((true));
// addSqlNugetReferenceToProjectFile stub
sinon.stub(utils, 'executeCommand').resolves('downloaded nuget package');
let result = await azureFunctionsUtils.promptAndUpdateConnectionStringSetting(fileUri, connectionInfo);
should(inputBoxStub.calledOnce).be.true('showInputBox should have been called');
should(quickPickStub.callCount).be.equal(2, 'showQuickPick should have been called');
should(result?.connectionStringSettingName).be.equal('testConnectionStringName', 'Should return testConnectionStringName from manually entered connection string name');
should(result?.connectionInfo).be.equal(connectionInfo, 'Should return connectionInfo');
});
it('Should use existing connection string when there are non-filtered connection strings found in local.settings.json', async () => {
let inputBoxSpy = sinon.spy(vscode.window, 'showInputBox');
let quickPickStub = sinon.stub(vscode.window, 'showQuickPick').onFirstCall().resolves({ label: 'test1' }); // user chooses existing setting name
// addSqlNugetReferenceToProjectFile stub
sinon.stub(utils, 'executeCommand').resolves('downloaded nuget package');
let connectionInfo: IConnectionInfo = createTestCredentials(); // create test connectionInfo
let result = await azureFunctionsUtils.promptAndUpdateConnectionStringSetting(fileUri, connectionInfo);
should(inputBoxSpy.notCalled).be.true('showInputBox should not have been called');
should(quickPickStub.callCount).be.equal(1, 'showQuickPick should have been called');
should(result?.connectionStringSettingName).be.equal('test1', 'Should return test1 setting chosen from quickpick');
should(result?.connectionInfo).be.equal(connectionInfo, 'Should return connectionInfo');
});
it('Should use user entered connection string setting name and manually enter connection string when no connection info given', async () => {
let quickPickStub = sinon.stub(vscode.window, 'showQuickPick').onFirstCall().resolves({ label: constants.createNewLocalAppSettingWithIcon }); // user chooses to create new connection string setting name
let inputBoxStub = sinon.stub(vscode.window, 'showInputBox').onFirstCall().resolves('testConnectionStringName'); // enter connection string setting name
// user chooses to manually enter connection string
quickPickStub.onSecondCall().resolves((constants.userConnectionString) as any);
inputBoxStub.onSecondCall().resolves('testConnectionString');
// setLocalAppSetting stubs
// fails if we dont set writeFile stub
sinon.stub(fs.promises, 'writeFile').resolves();
sinon.stub(azureFunctionsUtils, 'setLocalAppSetting').withArgs(sinon.match.any, 'testConnectionStringName', 'testConnectionString').resolves((true));
// addSqlNugetReferenceToProjectFile stub
sinon.stub(utils, 'executeCommand').resolves('downloaded nuget package');
let result = await azureFunctionsUtils.promptAndUpdateConnectionStringSetting(fileUri);
should(inputBoxStub.callCount).be.equal(2, 'showInputBox should have been called');
should(quickPickStub.callCount).be.equal(2, 'showQuickPick should have been called');
should(result?.connectionStringSettingName).be.equal('testConnectionStringName', 'Should return testConnectionStringName from manually entered connection string name');
});
it('Should prompt connection string method when user cancels out of selecting connection profile', async () => {
let quickPickStub = sinon.stub(vscode.window, 'showQuickPick').onFirstCall().resolves({ label: constants.createNewLocalAppSettingWithIcon }); // user chooses to create new connection string setting name
let inputBoxStub = sinon.stub(vscode.window, 'showInputBox').onFirstCall().resolves('testConnectionStringName'); // enter connection string setting name
// user chooses to manually enter connection string
quickPickStub.onSecondCall().resolves((constants.userConnectionString) as any);
inputBoxStub.onSecondCall().resolves(undefined);
quickPickStub.onThirdCall().resolves(undefined);
let result = await azureFunctionsUtils.promptAndUpdateConnectionStringSetting(fileUri);
should(quickPickStub.getCall(1).args).containDeepOrdered([
[constants.connectionProfile, constants.userConnectionString],
{
canPickMany: false,
title: constants.selectConnectionString,
ignoreFocusOut: true
}]
);
should(inputBoxStub.callCount).be.equal(2, 'showInputBox should have been called twice');
should(quickPickStub.callCount).be.equal(3, 'showQuickPick should have been called three times');
should(result?.connectionStringSettingName).be.equal(undefined, 'Should return undefined since user cancelled out of connection string setting name prompt');
});
it('Should prompt connection string method when user cancels out of manually entering connection string', async () => {
let quickPickStub = sinon.stub(vscode.window, 'showQuickPick').onFirstCall().resolves({ label: constants.createNewLocalAppSettingWithIcon }); // user chooses to create new connection string setting name
let inputBoxStub = sinon.stub(vscode.window, 'showInputBox').onFirstCall().resolves('testConnectionStringName'); // enter connection string setting name
// user chooses to manually enter connection string
quickPickStub.onSecondCall().resolves((constants.connectionProfile) as any);
sinon.stub(utils, 'getVscodeMssqlApi').resolves(testUtils.vscodeMssqlIExtension.object);
// user cancels out of connection profile prompt
testUtils.vscodeMssqlIExtension.setup(x => x.promptForConnection(true)).returns(() => Promise.resolve(undefined));
let result = await azureFunctionsUtils.promptAndUpdateConnectionStringSetting(fileUri);
should(quickPickStub.getCall(2).args).containDeepOrdered([
[constants.connectionProfile, constants.userConnectionString],
{
canPickMany: false,
title: constants.selectConnectionString,
ignoreFocusOut: true
}]
);
should(inputBoxStub.callCount).be.equal(1, 'showInputBox should have been called');
should(quickPickStub.callCount).be.equal(3, 'showQuickPick should have been called three times');
should(result?.connectionStringSettingName).be.equal(undefined, 'Should return undefined since user cancelled out of connection string setting name prompt');
});
it('Should prompt connection string settings when user cancels out of manually entering connection string name prompt', async () => {
let quickPickStub = sinon.stub(vscode.window, 'showQuickPick').onFirstCall().resolves({ label: constants.createNewLocalAppSettingWithIcon }); // user chooses to create new connection string setting name
let inputBoxStub = sinon.stub(vscode.window, 'showInputBox').onFirstCall().resolves(undefined); // enter connection string setting name
// cancel out of prompt for connection string settings
quickPickStub.onSecondCall().resolves(undefined);
let result = await azureFunctionsUtils.promptAndUpdateConnectionStringSetting(fileUri);
should(inputBoxStub.callCount).be.equal(1, 'showInputBox should have been called');
should(quickPickStub.callCount).be.equal(2, 'showQuickPick should have been called');
should(quickPickStub.getCall(1).args).containDeepOrdered([
[{ label: constants.createNewLocalAppSettingWithIcon }, { label: 'test1' }, { label: 'test2' }, { label: 'test3' }],
{
canPickMany: false,
title: constants.selectSetting,
ignoreFocusOut: true
}]
);
should(result?.connectionStringSettingName).be.equal(undefined, 'Should return undefined since user cancelled out of connection string setting name prompt');
});
});
it('Should prompt user to enter connection string setting name when local.settings.json values contains known connection strings', async () => {
// create fake connection string settings for local.setting.json to be used
// getLocalSettingsJson stub
sinon.stub(fs.promises, 'access').resolves();
// known connection string values that will be filtered out
sinon.stub(fs, 'readFileSync').withArgs(sinon.match.any).returns(
`{"IsEncrypted": false,
"Values": {"AzureWebJobsStorage": "testWebJobStorage","WEBSITE_TIME_ZONE":"testTimeZone"}}`
);
let inputBoxStub = sinon.stub(vscode.window, 'showInputBox').onFirstCall().resolves('testConnectionStringName'); // enter connection string setting name
// password prompt stub
sinon.stub(utils, 'getVscodeMssqlApi').resolves(testUtils.vscodeMssqlIExtension.object);
let quickPickStub = sinon.stub(vscode.window, 'showQuickPick').onFirstCall().resolves((constants.yesString) as any);
// getConnectionString stubs - in password prompt logic
let connectionInfo: IConnectionInfo = createTestCredentials(); // create test connectionInfo
let connectionDetails = { options: connectionInfo };
testUtils.vscodeMssqlIExtension.setup(x => x.getConnectionString(connectionDetails, true, false)).returns(() => Promise.resolve('testConnectionString'));
// fails if we dont set writeFile stub
sinon.stub(fs.promises, 'writeFile').resolves();
sinon.stub(azureFunctionsUtils, 'setLocalAppSetting').withArgs(sinon.match.any, 'testConnectionStringName', 'testConnectionString').resolves((true));
// addSqlNugetReferenceToProjectFile stub
sinon.stub(utils, 'executeCommand').resolves('downloaded nuget package');
let result = await azureFunctionsUtils.promptAndUpdateConnectionStringSetting(fileUri, connectionInfo);
should(inputBoxStub.calledOnce).be.true('showInputBox should have been called');
should(quickPickStub.callCount).be.equal(1, 'quickPickStub should have been called');
should(result?.connectionStringSettingName).be.equal('testConnectionStringName', 'Should return testConnectionStringName from manually entered connection string name');
should(result?.connectionInfo).be.equal(connectionInfo, 'Should return connectionInfo');
});
it('Should prompt user to enter connection string setting name when local.settings.json values are empty', async () => {
// create fake connection string settings for local.setting.json to be used
// getLocalSettingsJson stub
sinon.stub(fs.promises, 'access').resolves();
// empty values in local.settings.json
sinon.stub(fs, 'readFileSync').withArgs(sinon.match.any).returns(
`{"IsEncrypted": false,
"Values": {}}`
);
let inputBoxStub = sinon.stub(vscode.window, 'showInputBox').onFirstCall().resolves('testConnectionStringName'); // enter connection string setting name
// password prompt stub
sinon.stub(utils, 'getVscodeMssqlApi').resolves(testUtils.vscodeMssqlIExtension.object);
let quickPickStub = sinon.stub(vscode.window, 'showQuickPick').onFirstCall().resolves((constants.yesString) as any);
// getConnectionString stubs - in password prompt logic
let connectionInfo: IConnectionInfo = createTestCredentials(); // create test connectionInfo
let connectionDetails = { options: connectionInfo };
testUtils.vscodeMssqlIExtension.setup(x => x.getConnectionString(connectionDetails, true, false)).returns(() => Promise.resolve('testConnectionString'));
// fails if we dont set writeFile stub
sinon.stub(fs.promises, 'writeFile').resolves();
sinon.stub(azureFunctionsUtils, 'setLocalAppSetting').withArgs(sinon.match.any, 'testConnectionStringName', 'testConnectionString').resolves((true));
// addSqlNugetReferenceToProjectFile stub
sinon.stub(utils, 'executeCommand').resolves('downloaded nuget package');
let result = await azureFunctionsUtils.promptAndUpdateConnectionStringSetting(fileUri, connectionInfo);
should(inputBoxStub.calledOnce).be.true('showInputBox should have been called');
should(quickPickStub.callCount).be.equal(1, 'quickPickStub should have been called');
should(result?.connectionStringSettingName).be.equal('testConnectionStringName', 'Should return testConnectionStringName from manually entered connection string name');
should(result?.connectionInfo).be.equal(connectionInfo, 'Should return connectionInfo');
});
});
afterEach(function (): void {
sinon.restore();
});