diff --git a/src/extension.ts b/src/extension.ts index b5226b7f6..50b753f4c 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -25,6 +25,9 @@ export function activate(context: vscode.ExtensionContext): Promise { if (applyLocalization) { LocalizedConstants.loadLocalizedConstants(vscode.env.language); } + + // Exposed for testing purposes + vscode.commands.registerCommand('mssql.getControllerForTests', () => controller); return controller.activate(); } @@ -39,6 +42,10 @@ export function deactivate(): void { /** * Exposed for testing purposes */ -export function getController(): MainController { +export async function getController(): Promise { + if (!controller) { + let savedController: MainController = await vscode.commands.executeCommand('mssql.getControllerForTests'); + return savedController; + } return controller; } diff --git a/src/firewall/firewallService.ts b/src/firewall/firewallService.ts index 340f905bc..abc381145 100644 --- a/src/firewall/firewallService.ts +++ b/src/firewall/firewallService.ts @@ -36,6 +36,13 @@ export class FirewallService { return this._account; } + /** + * Public for testing purposes only + */ + public set token(value: any) { + this._token = value; + } + private convertToAzureAccount(azureSession: AzureSession): Account { let tenant = { displayName: Constants.tenantDisplayName, diff --git a/src/languageservice/httpClient.ts b/src/languageservice/httpClient.ts index 05e803ec2..a916ca7b8 100644 --- a/src/languageservice/httpClient.ts +++ b/src/languageservice/httpClient.ts @@ -146,7 +146,7 @@ export default class HttpClient implements IHttpClient { /* * Interface to store the values needed to calculate download percentage */ -interface IDownloadProgress { +export interface IDownloadProgress { packageSize: number; downloadedBytes: number; downloadPercentage: number; diff --git a/test/firewallService.test.ts b/test/firewallService.test.ts new file mode 100644 index 000000000..440b00c78 --- /dev/null +++ b/test/firewallService.test.ts @@ -0,0 +1,83 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ +import * as vscode from 'vscode'; +import * as TypeMoq from 'typemoq'; +import SqlToolsServiceClient from '../src/languageservice/serviceclient'; +import { FirewallService } from '../src/firewall/firewallService'; +import { HandleFirewallRuleRequest, HandleFirewallRuleResponse, + CreateFirewallRuleRequest, CreateFirewallRuleResponse, HandleFirewallRuleParams } from '../src/models/contracts/firewall/firewallRequest'; +import VscodeWrapper from '../src/controllers/vscodeWrapper'; +import { assert } from 'chai'; +import { AzureSession } from '../src/models/interfaces'; + + +suite('Firewall Service Tests', () => { + let firewallService: FirewallService; + let client: TypeMoq.IMock; + let vscodeWrapper: TypeMoq.IMock; + + setup(() => { + client = TypeMoq.Mock.ofType(SqlToolsServiceClient, TypeMoq.MockBehavior.Loose); + let mockHandleFirewallResponse: HandleFirewallRuleResponse = { + result: true, + ipAddress: '128.0.0.0' + }; + let mockCreateFirewallRuleResponse: CreateFirewallRuleResponse = { + result: true, + errorMessage: '' + }; + client.setup(c => c.sendResourceRequest(HandleFirewallRuleRequest.type, TypeMoq.It.isAny())).returns(() => Promise.resolve(mockHandleFirewallResponse)); + client.setup(c => c.sendResourceRequest(CreateFirewallRuleRequest.type, TypeMoq.It.isAny())).returns(() => Promise.resolve(mockCreateFirewallRuleResponse)); + vscodeWrapper = TypeMoq.Mock.ofType(VscodeWrapper, TypeMoq.MockBehavior.Loose); + let mockSession: AzureSession = { + environment: undefined, + userId: 'test', + tenantId: 'test', + credentials: undefined + }; + let mockExtension: vscode.Extension = { + id: '', + extensionKind: undefined, + extensionPath: '', + isActive: true, + packageJSON: undefined, + activate: undefined, + exports: { + sessions: [mockSession] + } + }; + vscodeWrapper.setup(v => v.azureAccountExtension).returns(() => mockExtension); + firewallService = new FirewallService(client.object, vscodeWrapper.object); + }); + + test('isSignedIn Test', () => { + let isSignedIn = firewallService.isSignedIn; + assert.isNotTrue(isSignedIn, 'Firewall Service should not be signed in initially'); + firewallService.isSignedIn = true; + assert.isTrue(firewallService.isSignedIn, 'Firewall Service should be signed in once set'); + }); + + test('Handle Firewall Rule test', async () => { + let result = await firewallService.handleFirewallRule(12345, 'firewall error!'); + assert.isNotNull(result, 'Handle Firewall Rule request is sent successfully'); + }); + + test('Create Firewall Rule Test', async () => { + let server = 'test_server'; + let startIpAddress = '1.2.3.1'; + let endIpAddress = '1.2.3.255'; + firewallService.isSignedIn = true; + let mockToken = { + expiresOn: new Date(), + resource: undefined, + tokenType: 'test', + accessToken: 'test_token' + } + firewallService.token = mockToken; + let result = await firewallService.createFirewallRule(server, startIpAddress, endIpAddress); + assert.isNotNull(result, 'Create Firewall Rule request is sent successfully'); + }); +}); + diff --git a/test/initialization.test.ts b/test/initialization.test.ts index 9d9e28f6c..eb26cc0b4 100644 --- a/test/initialization.test.ts +++ b/test/initialization.test.ts @@ -34,9 +34,9 @@ suite('Initialization Tests', () => { test('Connection manager is initialized properly', () => { // Wait for the extension to activate - ensureExtensionIsActive().then(() => { + ensureExtensionIsActive().then(async () => { // Verify that the connection manager was initialized properly - let controller: MainController = Extension.getController(); + let controller: MainController = await Extension.getController(); let connectionManager: ConnectionManager = controller.connectionManager; assert.notStrictEqual(undefined, connectionManager.client); }); diff --git a/test/languageService.test.ts b/test/languageService.test.ts new file mode 100644 index 000000000..594143ca2 --- /dev/null +++ b/test/languageService.test.ts @@ -0,0 +1,68 @@ +import DecompressProvider from "../src/languageservice/decompressProvider"; +import { IPackage, IStatusView } from "../src/languageservice/interfaces"; +import { ILogger } from "../src/models/interfaces"; +import { assert } from "chai"; +import HttpClient, { IDownloadProgress } from "../src/languageservice/httpClient"; +import { HttpModule } from "../out/src/views/htmlcontent/src/js/lib/@angular/http"; + +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ + +suite('Language Service Tests', () => { + + suite('Decompress Provider Tests', () => { + let decompressProvider = new DecompressProvider(); + + test('Decompress package test', () => { + let testPackage: IPackage = { + url: 'test_url', + tmpFile: undefined + }; + let testLogger: ILogger = { + logDebug: undefined, + increaseIndent: undefined, + decreaseIndent: undefined, + append: undefined, + appendLine: undefined + + }; + decompressProvider.decompress(testPackage, testLogger).catch((err) => { + assert.isNotNull(err, 'Should throw an error'); + }); + }); + }); + + suite('HttpClient Tests', () => { + let httpClient = new HttpClient(); + + test('handleDataReceivedEvent test', () => { + let mockProgress: IDownloadProgress = { + packageSize: 10, + downloadedBytes: 0, + downloadPercentage: 0, + dots: 0 + }; + let testLogger: ILogger = { + logDebug: () => undefined, + increaseIndent: () => undefined, + decreaseIndent: () => undefined, + append: () => undefined, + appendLine: () => undefined + + }; + let mockStatusView: IStatusView = { + installingService: () => undefined, + serviceInstalled: () => undefined, + serviceInstallationFailed: () => undefined, + updateServiceDownloadingProgress: (downloadPercentage: number) => undefined + } + httpClient.handleDataReceivedEvent(mockProgress, [1,2,3,4,5], testLogger, mockStatusView); + assert.strictEqual(mockProgress.downloadPercentage, 50); + assert.strictEqual(mockProgress.downloadedBytes, 5); + assert.strictEqual(mockProgress.dots, 10); + }); + }); +}); + diff --git a/test/mainController.test.ts b/test/mainController.test.ts index a1bedef97..c2f1bed98 100644 --- a/test/mainController.test.ts +++ b/test/mainController.test.ts @@ -17,7 +17,7 @@ import VscodeWrapper from '../src/controllers/vscodeWrapper'; import { TestExtensionContext } from './stubs'; import assert = require('assert'); -suite('MainController Tests', async () => { +suite('MainController Tests', () => { let document: vscode.TextDocument; let newDocument: vscode.TextDocument; let mainController: MainController; @@ -28,52 +28,7 @@ suite('MainController Tests', async () => { let docUriCallback: string; let newDocUriCallback: string; - function ensureExtensionIsActive(): Promise { - return new Promise((resolve, reject) => { - waitForExtensionToBeActive(resolve); - }); - } - - function waitForExtensionToBeActive(resolve): void { - if (typeof(vscode.extensions.getExtension('ms-mssql.mssql')) === 'undefined' || - !vscode.extensions.getExtension('ms-mssql.mssql').isActive) { - setTimeout(waitForExtensionToBeActive.bind(this, resolve), 50); - } else { - resolve(); - } - } - - async function setupMaincontroller(): Promise { - return ensureExtensionIsActive().then(() => { - // Using the mainController that was instantiated with the extension - mainController = Extension.getController(); - - // Setting up a mocked connectionManager - connectionManager = TypeMoq.Mock.ofType(ConnectionManager); - mainController.connectionManager = connectionManager.object; - - untitledSqlDocumentService = TypeMoq.Mock.ofType(UntitledSqlDocumentService); - mainController.untitledSqlDocumentService = untitledSqlDocumentService.object; - - // Watching these functions and input paramters - connectionManager.setup(x => x.onDidOpenTextDocument(TypeMoq.It.isAny())).callback((doc) => { - docUriCallback = doc.uri.toString(); - }); - - connectionManager.setup(x => x.onDidCloseTextDocument(TypeMoq.It.isAny())).callback((doc) => { - docUriCallback = doc.uri.toString(); - }); - - connectionManager.setup(x => x.transferFileConnection(TypeMoq.It.isAny(), TypeMoq.It.isAny())).callback((doc, newDoc) => { - docUriCallback = doc; - newDocUriCallback = newDoc; - }); - - return mainController; - }); - } - - setup(() => { + setup(async () => { // Setup a standard document and a new document docUri = 'docURI.sql'; newDocUri = 'newDocURI.sql'; @@ -99,9 +54,32 @@ suite('MainController Tests', async () => { // Resetting call back variables docUriCallback = ''; newDocUriCallback = ''; - }); - mainController = await setupMaincontroller(); + + // Using the mainController that was instantiated with the extension + mainController = await Extension.getController(); + + // Setting up a mocked connectionManager + connectionManager = TypeMoq.Mock.ofType(ConnectionManager); + mainController.connectionManager = connectionManager.object; + + untitledSqlDocumentService = TypeMoq.Mock.ofType(UntitledSqlDocumentService); + mainController.untitledSqlDocumentService = untitledSqlDocumentService.object; + + // Watching these functions and input paramters + connectionManager.setup(x => x.onDidOpenTextDocument(TypeMoq.It.isAny())).callback((doc) => { + docUriCallback = doc.uri.toString(); + }); + + connectionManager.setup(x => x.onDidCloseTextDocument(TypeMoq.It.isAny())).callback((doc) => { + docUriCallback = doc.uri.toString(); + }); + + connectionManager.setup(x => x.transferFileConnection(TypeMoq.It.isAny(), TypeMoq.It.isAny())).callback((doc, newDoc) => { + docUriCallback = doc; + newDocUriCallback = newDoc; + }); + }); // Standard closed document event test test('onDidCloseTextDocument should propogate onDidCloseTextDocument to connectionManager' , () => {