From cb8320ca836585f210b218f983fca080e82b53a2 Mon Sep 17 00:00:00 2001 From: Kim Santiago <31145923+kisantia@users.noreply.github.com> Date: Thu, 16 Sep 2021 11:19:03 -0700 Subject: [PATCH] Adding a few tests for Add SQL binding (#17079) * initial changes * add a couple more tests --- .../dialogs/addSqlBindingQuickpick.test.ts | 81 +++++++++++++++++++ .../src/test/packageHelper.test.ts | 61 ++++++++++++++ .../src/test/testContext.ts | 19 +++++ 3 files changed, 161 insertions(+) create mode 100644 extensions/sql-database-projects/src/test/dialogs/addSqlBindingQuickpick.test.ts create mode 100644 extensions/sql-database-projects/src/test/packageHelper.test.ts diff --git a/extensions/sql-database-projects/src/test/dialogs/addSqlBindingQuickpick.test.ts b/extensions/sql-database-projects/src/test/dialogs/addSqlBindingQuickpick.test.ts new file mode 100644 index 0000000000..095822d571 --- /dev/null +++ b/extensions/sql-database-projects/src/test/dialogs/addSqlBindingQuickpick.test.ts @@ -0,0 +1,81 @@ +/*--------------------------------------------------------------------------------------------- + * 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 } 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 { + sinon.stub(utils, 'getAzureFunctionService').resolves(testContext.azureFunctionService.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 { + sinon.stub(utils, 'getAzureFunctionService').resolves(testContext.azureFunctionService.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'] + }); + }); + 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]}'`); + }); +}); + diff --git a/extensions/sql-database-projects/src/test/packageHelper.test.ts b/extensions/sql-database-projects/src/test/packageHelper.test.ts new file mode 100644 index 0000000000..840e27c742 --- /dev/null +++ b/extensions/sql-database-projects/src/test/packageHelper.test.ts @@ -0,0 +1,61 @@ +/*--------------------------------------------------------------------------------------------- + * 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 projectPath = 'dummy\\project\\path.csproj'; + const result = packageHelper.constructAddPackageArguments(projectPath, 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 projectPath = 'dummy\\project\\path.csproj'; + const result = packageHelper.constructAddPackageArguments(projectPath, 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 { + sinon.stub(azureFunctionUtils, 'getAFProjectContainingFile').resolves(undefined); + const spy = sinon.spy(vscode.window, 'showInformationMessage'); + + await packageHelper.addPackageToAFProjectContainingFile('', constants.sqlExtensionPackageName); + should(spy.calledOnce).be.true('showInformationMessage should have been called exactly once'); + }); +}); diff --git a/extensions/sql-database-projects/src/test/testContext.ts b/extensions/sql-database-projects/src/test/testContext.ts index 1e42a695be..456f677281 100644 --- a/extensions/sql-database-projects/src/test/testContext.ts +++ b/extensions/sql-database-projects/src/test/testContext.ts @@ -8,10 +8,12 @@ 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; + azureFunctionService: TypeMoq.IMock; outputChannel: vscode.OutputChannel; } @@ -119,6 +121,22 @@ export class MockDacFxService implements mssql.IDacFxService { public validateStreamingJob(_: string, __: string): Thenable { 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 { return Promise.resolve(mockResultStatus); } + getAzureFunctions(_: string): Thenable { return Promise.resolve(mockGetAzureFunctionsResult); } +} + export function createContext(): TestContext { let extensionPath = path.join(__dirname, '..', '..'); @@ -149,6 +167,7 @@ export function createContext(): TestContext { extension: undefined as any }, dacFxService: TypeMoq.Mock.ofType(MockDacFxService), + azureFunctionService: TypeMoq.Mock.ofType(MockAzureFunctionService), outputChannel: { name: '', append: () => { },