Removing ApiWrapper and adding sinon (#11340)

* Added sinon
removed api wrapper
removed unnecesaary utils

* merged from testfix

* merged from aasim/import/downloadTestFix

* merge from aasim/import/downloadTestFix
This commit is contained in:
Aasim Khan
2020-07-14 14:53:18 -07:00
committed by GitHub
parent cabbbb56f2
commit 24f6cd2e5b
19 changed files with 212 additions and 322 deletions

View File

@@ -1,88 +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 vscode from 'vscode';
import * as azdata from 'azdata';
/**
* Wrapper class to act as a facade over VSCode and Data APIs and allow us to test/mock callbacks into
* this API from our code
*/
export class ApiWrapper {
public createOutputChannel(name: string): vscode.OutputChannel {
return vscode.window.createOutputChannel(name);
}
public getExtension(extensionId: string): vscode.Extension<any> | undefined {
return vscode.extensions.getExtension(extensionId);
}
public getUriForConnection(connectionId: string): Thenable<string> {
return azdata.connection.getUriForConnection(connectionId);
}
public getProvider<T extends azdata.DataProvider>(providerId: string, providerType: azdata.DataProviderType): T {
return azdata.dataprotocol.getProvider<T>(providerId, providerType);
}
public getCurrentConnection(): Thenable<azdata.connection.ConnectionProfile> {
return azdata.connection.getCurrentConnection();
}
public openConnectionDialog(providers?: string[]): Thenable<azdata.connection.Connection> {
return azdata.connection.openConnectionDialog(providers);
}
public showErrorMessage(message: string, ...items: string[]): Thenable<string | undefined> {
return vscode.window.showErrorMessage(message, ...items);
}
public createWizard(title: string): azdata.window.Wizard {
return azdata.window.createWizard(title);
}
public createWizardPage(title: string): azdata.window.WizardPage {
return azdata.window.createWizardPage(title);
}
public createButton(lable: string) {
return azdata.window.createButton(lable);
}
public showOpenDialog(options: vscode.OpenDialogOptions): Thenable<vscode.Uri[] | undefined> {
return vscode.window.showOpenDialog(options);
}
public getActiveConnections(): Thenable<azdata.connection.Connection[]> {
return azdata.connection.getActiveConnections();
}
public listDatabases(connectionId: string): Thenable<string[]> {
return azdata.connection.listDatabases(connectionId);
}
public openExternal(target: vscode.Uri): Thenable<boolean> {
return vscode.env.openExternal(target);
}
public getConfiguration(section?: string, resource?: vscode.Uri | null): vscode.WorkspaceConfiguration {
return vscode.workspace.getConfiguration(section, resource);
}
public registerTask(task: string, callback: azdata.tasks.ITaskHandler) {
azdata.tasks.registerTask(task, callback);
}
public getCredentials(connectionId: string) {
return azdata.connection.getCredentials(connectionId);
}
public getConnectionString(connectionId: string, includePassword: boolean) {
return azdata.connection.getConnectionString(connectionId, includePassword);
}
}

View File

@@ -11,22 +11,18 @@ import { FlatFileWizard } from '../wizard/flatFileWizard';
import { ServiceClient } from '../services/serviceClient';
import { ApiType, managerInstance } from '../services/serviceApiManager';
import { FlatFileProvider } from '../services/contracts';
import { ApiWrapper } from '../common/apiWrapper';
/**
* The main controller class that initializes the extension
*/
export default class MainController extends ControllerBase {
private _outputChannel: vscode.OutputChannel;
private _apiWrapper: ApiWrapper;
public constructor(
context: vscode.ExtensionContext,
apiWrapper: ApiWrapper
) {
super(context);
this._apiWrapper = apiWrapper;
this._outputChannel = this._apiWrapper.createOutputChannel(constants.serviceName);
this._outputChannel = vscode.window.createOutputChannel(constants.serviceName);
}
/**
*/
@@ -39,13 +35,13 @@ export default class MainController extends ControllerBase {
this.initializeFlatFileProvider(provider);
resolve(true);
});
await new ServiceClient(this._outputChannel, this._apiWrapper).startService(this._context);
await new ServiceClient(this._outputChannel).startService(this._context);
});
}
private initializeFlatFileProvider(provider: FlatFileProvider) {
this._apiWrapper.registerTask(constants.flatFileImportStartCommand, (profile: azdata.IConnectionProfile, ...args: any[]) => new FlatFileWizard(provider, this._apiWrapper).start(profile, args));
azdata.tasks.registerTask(constants.flatFileImportStartCommand, (profile: azdata.IConnectionProfile, ...args: any[]) => new FlatFileWizard(provider).start(profile, args));
}
}

View File

@@ -7,16 +7,13 @@ import * as vscode from 'vscode';
import ControllerBase from './controllers/controllerBase';
import MainController from './controllers/mainController';
import { ApiWrapper } from './common/apiWrapper';
let controllers: ControllerBase[] = [];
export async function activate(context: vscode.ExtensionContext): Promise<void> {
let apiWrapper = new ApiWrapper();
// Start the main controller
let mainController = new MainController(context, apiWrapper);
let mainController = new MainController(context);
controllers.push(mainController);
context.subscriptions.push(mainController);

View File

@@ -16,14 +16,12 @@ import { Telemetry, LanguageClientErrorHandler } from './telemetry';
import * as Constants from '../common/constants';
import { TelemetryFeature, FlatFileImportFeature } from './features';
import { promises as fs } from 'fs';
import { ApiWrapper } from '../common/apiWrapper';
export class ServiceClient {
private statusView: vscode.StatusBarItem;
constructor(
private outputChannel: vscode.OutputChannel,
private _apiWrapper: ApiWrapper
) {
this.statusView = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
}
@@ -69,8 +67,8 @@ export class ServiceClient {
public async downloadBinaries(context: vscode.ExtensionContext, rawConfig: Buffer): Promise<string> {
const config = JSON.parse(rawConfig.toString());
config.installDirectory = path.join(context.extensionPath, config.installDirectory);
config.proxy = this._apiWrapper.getConfiguration('http').get('proxy');
config.strictSSL = this._apiWrapper.getConfiguration('http').get('proxyStrictSSL') || true;
config.proxy = vscode.workspace.getConfiguration('http').get('proxy');
config.strictSSL = vscode.workspace.getConfiguration('http').get('proxyStrictSSL') || true;
const serverdownloader = new ServerProvider(config);
serverdownloader.eventEmitter.onAny(this.generateHandleServerProviderEvent());
return serverdownloader.getOrDownloadServer();

View File

@@ -3,42 +3,21 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as TypeMoq from 'typemoq';
import { ApiWrapper } from '../../common/apiWrapper';
import MainController from '../../controllers/mainController';
import * as constants from '../../common/constants';
import * as should from 'should';
import * as path from 'path';
import { ImportTestUtils, TestExtensionContext } from '../utils.test';
import * as should from 'should';
describe('Main Controller', function () {
let testExtensionContext: TestExtensionContext;
let mockApiWrapper: TypeMoq.IMock<ApiWrapper>;
let extensionPath: string;
beforeEach(async function () {
extensionPath = await ImportTestUtils.getExtensionPath();
// creating a mock Extension Context with current extensionPath
testExtensionContext = await ImportTestUtils.getTestExtensionContext();
mockApiWrapper = TypeMoq.Mock.ofType(ApiWrapper);
});
it('Should download required binaries and register flatFileImportStartCommand after activate is called', async function () {
this.timeout(50000);
// using vscode and azdata APIs available during tests
mockApiWrapper.callBase = true;
let mainController = new MainController(testExtensionContext, mockApiWrapper.object);
await mainController.activate();
// verifying that the task is registered.
mockApiWrapper.verify(x => x.registerTask(constants.flatFileImportStartCommand, TypeMoq.It.isAny()), TypeMoq.Times.once());
//Checking if .net code files are downloaded
should.equal(await ImportTestUtils.checkPathExists(path.join(extensionPath, 'flatfileimportservice')), true);
it('Should register task flatFileImportStartCommand after activate is called', async function () {
let mainController = new MainController(testExtensionContext);
should.doesNotThrow(() => mainController.activate());
});
});

View File

@@ -7,7 +7,6 @@ import * as azdata from 'azdata';
import * as vscode from 'vscode';
import { ImportDataModel, ColumnMetadata } from '../wizard/api/models';
import { FlatFileProvider, PROSEDiscoveryParams, InsertDataParams, GetColumnInfoParams, ChangeColumnSettingsParams, PROSEDiscoveryResponse, InsertDataResponse, ChangeColumnSettingsResponse, GetColumnInfoResponse } from '../services/contracts';
import * as fs from 'fs';
export class ImportTestUtils {
@@ -37,12 +36,6 @@ export class ImportTestUtils {
} as azdata.connection.ConnectionProfile;
}
public static async checkPathExists(path: string): Promise<boolean> {
return fs.promises.access(path, fs.constants.F_OK)
.then(() => true)
.catch(() => false);
}
public static async getExtensionPath(): Promise<string> {
return await vscode.extensions.getExtension('Microsoft.import').extensionPath;
}
@@ -134,73 +127,10 @@ export class TestQueryProvider implements azdata.QueryProvider {
throw new Error('Method not implemented.');
}
handle?: number;
providerId: string;
providerId: string = 'testProviderId';
}
export class TestWizard implements azdata.window.Wizard {
title: string;
pages: azdata.window.WizardPage[];
currentPage: number;
doneButton: azdata.window.Button;
cancelButton: azdata.window.Button;
generateScriptButton: azdata.window.Button = azdata.window.createButton('testButton');
nextButton: azdata.window.Button;
backButton: azdata.window.Button;
customButtons: azdata.window.Button[];
displayPageTitles: boolean;
onPageChanged: vscode.Event<azdata.window.WizardPageChangeInfo> = new vscode.EventEmitter<any>().event;
addPage(page: azdata.window.WizardPage, index?: number): Thenable<void> {
throw new Error('Method not implemented.');
}
removePage(index: number): Thenable<void> {
throw new Error('Method not implemented.');
}
setCurrentPage(index: number): Thenable<void> {
throw new Error('Method not implemented.');
}
open(): Thenable<void> {
throw new Error('Method not implemented.');
}
close(): Thenable<void> {
throw new Error('Method not implemented.');
}
registerNavigationValidator(validator: (pageChangeInfo: azdata.window.WizardPageChangeInfo) => boolean | Thenable<boolean>): void {
throw new Error('Method not implemented.');
}
message: azdata.window.DialogMessage;
registerOperation(operationInfo: azdata.BackgroundOperationInfo): void {
throw new Error('Method not implemented.');
}
}
export class TestWizardPage implements azdata.window.WizardPage {
title: string;
content: string;
customButtons: azdata.window.Button[];
enabled: boolean;
description: string;
registerContent(handler: (view: azdata.ModelView) => Thenable<void>): void {
throw new Error('Method not implemented.');
}
modelView: azdata.ModelView;
valid: boolean;
onValidityChanged: vscode.Event<boolean>;
}
export class TestButton implements azdata.window.Button {
label: string;
enabled: boolean;
hidden: boolean;
focused?: boolean;
constructor(private onClickEmitter: vscode.EventEmitter<void>) {
}
onClick: vscode.Event<void> = this.onClickEmitter.event;
position?: azdata.window.DialogButtonPosition;
}
export class TestExtensionContext implements vscode.ExtensionContext {
extensionMode: vscode.ExtensionMode;
subscriptions: { dispose(): any; }[];

View File

@@ -6,32 +6,34 @@
import * as TypeMoq from 'typemoq';
import * as azdata from 'azdata';
import { FlatFileWizard } from '../../../wizard/flatFileWizard';
import { ApiWrapper } from '../../../common/apiWrapper';
import { ImportDataModel } from '../../../wizard/api/models';
import { TestImportDataModel, ImportTestUtils } from '../../utils.test';
import { FileConfigPage } from '../../../wizard/pages/fileConfigPage';
import * as should from 'should';
import * as sinon from 'sinon';
describe('import extension wizard pages', function () {
describe('Base page tests', function () {
let mockFlatFileWizard: TypeMoq.IMock<FlatFileWizard>;
let mockApiWrapper: TypeMoq.IMock<ApiWrapper>;
let mockImportModel: TypeMoq.IMock<ImportDataModel>;
beforeEach(function () {
mockApiWrapper = TypeMoq.Mock.ofType(ApiWrapper);
mockFlatFileWizard = TypeMoq.Mock.ofType(FlatFileWizard, TypeMoq.MockBehavior.Loose, undefined, TypeMoq.It.isAny(), mockApiWrapper.object);
mockFlatFileWizard = TypeMoq.Mock.ofType(FlatFileWizard, TypeMoq.MockBehavior.Loose, undefined, TypeMoq.It.isAny());
mockImportModel = TypeMoq.Mock.ofType(TestImportDataModel, TypeMoq.MockBehavior.Loose);
});
afterEach(function (): void {
sinon.restore();
});
it('getDatabaseValue returns active database first', async function () {
// setting up the environment
let databases: string[] = ['testdb1', 'testdb2', 'testdb3'];
let activeDatabase: string = 'testdb2';
// setting up mocks
let importPage = new FileConfigPage(mockFlatFileWizard.object, TypeMoq.It.isAny(), mockImportModel.object, TypeMoq.It.isAny(), TypeMoq.It.isAny(), mockApiWrapper.object);
mockApiWrapper.setup(x => x.listDatabases(TypeMoq.It.isAnyString())).returns(async () => { return databases; });
let importPage = new FileConfigPage(mockFlatFileWizard.object, TypeMoq.It.isAny(), mockImportModel.object, TypeMoq.It.isAny(), TypeMoq.It.isAny());
sinon.stub(azdata.connection, 'listDatabases').returns(Promise.resolve(databases));
mockImportModel.object.server = {
providerName: 'MSSQL',
connectionId: 'testConnectionId',
@@ -52,10 +54,10 @@ describe('import extension wizard pages', function () {
it('getServerValue returns null on no active connection', async function () {
let importPage = new FileConfigPage(mockFlatFileWizard.object, TypeMoq.It.isAny(), mockImportModel.object, TypeMoq.It.isAny(), TypeMoq.It.isAny(), mockApiWrapper.object);
let importPage = new FileConfigPage(mockFlatFileWizard.object, TypeMoq.It.isAny(), mockImportModel.object, TypeMoq.It.isAny(), TypeMoq.It.isAny());
// mocking getActive connection to return null
mockApiWrapper.setup(x => x.getActiveConnections()).returns(async () => { return undefined; });
let getActiveConnectionStub = sinon.stub(azdata.connection, 'getActiveConnections').returns(Promise.resolve(undefined));
let serverValues = await importPage.getServerValues();
@@ -63,7 +65,7 @@ describe('import extension wizard pages', function () {
should.equal(serverValues, undefined, 'getServer should be undefined for no active connections');
// mocking getActive connection returns empty array
mockApiWrapper.setup(x => x.getActiveConnections()).returns(async () => { return [] as azdata.connection.Connection[]; });
getActiveConnectionStub.returns(Promise.resolve([] as azdata.connection.Connection[]));
serverValues = await importPage.getServerValues();
@@ -100,8 +102,8 @@ describe('import extension wizard pages', function () {
}
];
let importPage = new FileConfigPage(mockFlatFileWizard.object, TypeMoq.It.isAny(), mockImportModel.object, TypeMoq.It.isAny(), TypeMoq.It.isAny(), mockApiWrapper.object);
mockApiWrapper.setup(x => x.getActiveConnections()).returns(async () => { return testActiveConnections; });
let importPage = new FileConfigPage(mockFlatFileWizard.object, TypeMoq.It.isAny(), mockImportModel.object, TypeMoq.It.isAny(), TypeMoq.It.isAny());
sinon.stub(azdata.connection, 'getActiveConnections').returns(Promise.resolve(testActiveConnections));
mockImportModel.object.server = ImportTestUtils.getTestServer();
// the second connection should be the first element in the array as it is active

View File

@@ -6,16 +6,22 @@
import * as TypeMoq from 'typemoq';
import * as vscode from 'vscode';
import * as azdata from 'azdata';
import { ApiWrapper } from '../../common/apiWrapper';
import { FlatFileWizard } from '../../wizard/flatFileWizard';
import { ImportTestUtils, TestWizard, TestWizardPage, TestButton } from '../utils.test';
import { ImportTestUtils } from '../utils.test';
import * as should from 'should';
import * as sinon from 'sinon';
describe('import extension flat file wizard', function () {
let mockApiWrapper: TypeMoq.IMock<ApiWrapper>;
this.beforeEach(function () {
mockApiWrapper = TypeMoq.Mock.ofType(ApiWrapper);
let showErrorMessageSpy: sinon.SinonSpy;
this.beforeEach(function() {
showErrorMessageSpy = sinon.spy(vscode.window, 'showErrorMessage');
});
this.afterEach(function () {
sinon.restore();
});
it('opens connectionDialog when there are no active connections', async function () {
let testConnection: azdata.connection.Connection = {
providerName: 'MSSQL',
@@ -24,46 +30,43 @@ describe('import extension flat file wizard', function () {
};
// There is no current connection.
mockApiWrapper.setup(x => x.getCurrentConnection()).returns(() => { return undefined; });
sinon.stub(azdata.connection, 'getCurrentConnection').returns(undefined);
// openConnectionDialog returns a test connection
mockApiWrapper.setup(x => x.openConnectionDialog(TypeMoq.It.isAny())).returns(async () => { return testConnection; });
let openConnectionDialogSpy = sinon.stub(azdata.connection, 'openConnectionDialog').returns(Promise.resolve(testConnection));
let testFlatFileWizard = new FlatFileWizard(TypeMoq.It.isAny(), mockApiWrapper.object);
let testFlatFileWizard = new FlatFileWizard(TypeMoq.It.isAny());
await testFlatFileWizard.getConnectionId();
// openConnectionDialog will be called once
mockApiWrapper.verify(x => x.openConnectionDialog(TypeMoq.It.isAny()), TypeMoq.Times.once());
sinon.assert.calledOnce(openConnectionDialogSpy);
});
it('shows error message when an invalid connection is selected', async function () {
// The active connection doesn't have a valid Provider
let testConnectionProfile: azdata.connection.ConnectionProfile = ImportTestUtils.getTestConnectionProfile();
mockApiWrapper.setup(x => x.getCurrentConnection()).returns(() => { return Promise.resolve(testConnectionProfile); });
mockApiWrapper.setup(x => x.openConnectionDialog(TypeMoq.It.isAny())).returns(() => { return undefined; });
sinon.stub(azdata.connection, 'getCurrentConnection').returns(Promise.resolve(testConnectionProfile));
sinon.stub(azdata.connection, 'openConnectionDialog').returns(undefined);
let testFlatFileWizard = new FlatFileWizard(TypeMoq.It.isAny(), mockApiWrapper.object);
let testFlatFileWizard = new FlatFileWizard(TypeMoq.It.isAny());
await testFlatFileWizard.getConnectionId();
mockApiWrapper.verify(x => x.showErrorMessage(TypeMoq.It.isAny()), TypeMoq.Times.once());
sinon.assert.calledOnce(showErrorMessageSpy);
});
it('shows error message when no connection is selected', async function () {
// The active connection doesn't have a valid Provider
mockApiWrapper.setup(x => x.getCurrentConnection()).returns(() => { return undefined; });
mockApiWrapper.setup(x => x.openConnectionDialog(TypeMoq.It.isAny())).returns(() => { return undefined; });
sinon.stub(azdata.connection, 'getCurrentConnection').returns(Promise.resolve(undefined));
sinon.stub(azdata.connection, 'openConnectionDialog').returns(undefined);
let testFlatFileWizard = new FlatFileWizard(TypeMoq.It.isAny(), mockApiWrapper.object);
let testFlatFileWizard = new FlatFileWizard(TypeMoq.It.isAny());
await testFlatFileWizard.getConnectionId();
mockApiWrapper.verify(x => x.showErrorMessage(TypeMoq.It.isAny()), TypeMoq.Times.once());
sinon.assert.calledOnce(showErrorMessageSpy);
});
it('getConnection returns active connection', async function () {
@@ -71,9 +74,9 @@ describe('import extension flat file wizard', function () {
testConnectionProfile.providerId = 'MSSQL';
//mocking an active connection
mockApiWrapper.setup(x => x.getCurrentConnection()).returns(async () => { return testConnectionProfile; })
sinon.stub(azdata.connection, 'getCurrentConnection').returns(Promise.resolve(testConnectionProfile));
let testFlatFileWizard = new FlatFileWizard(TypeMoq.It.isAny(), mockApiWrapper.object);
let testFlatFileWizard = new FlatFileWizard(TypeMoq.It.isAny());
//getConnectionID should return the connectionId of active connection
let connectionId = await testFlatFileWizard.getConnectionId();
@@ -83,23 +86,15 @@ describe('import extension flat file wizard', function () {
it('should initialize all pages', async function () {
let testConnectionProfile = ImportTestUtils.getTestConnectionProfile();
testConnectionProfile.providerId = 'MSSQL';
mockApiWrapper.setup(x => x.getCurrentConnection()).returns(async () => { return testConnectionProfile; });
let onClick: vscode.EventEmitter<any> = new vscode.EventEmitter<any>();
let mockWizard = TypeMoq.Mock.ofType(TestWizard);
let mockWizardPage = TypeMoq.Mock.ofType(TestWizardPage);
let mockButton = TypeMoq.Mock.ofType(TestButton, TypeMoq.MockBehavior.Loose, undefined, onClick);
sinon.stub(azdata.connection, 'getCurrentConnection').returns(Promise.resolve(testConnectionProfile));
let testProvider = {
providerId: 'testProviderId',
connectionProfile: ImportTestUtils.getTestConnectionProfile()
};
// Mocking wizard component creation
mockApiWrapper.setup(x => x.createWizard(TypeMoq.It.isAnyString())).returns(() => { return mockWizard.object; });
mockApiWrapper.setup(x => x.createWizardPage(TypeMoq.It.isAnyString())).returns(() => { return mockWizardPage.object; });
mockApiWrapper.setup(x => x.createButton(TypeMoq.It.isAnyString())).returns(() => { return mockButton.object; });
let testFlatFileWizard = new FlatFileWizard(TypeMoq.It.isAny(), mockApiWrapper.object);
let testFlatFileWizard = new FlatFileWizard(TypeMoq.It.isAny());
await testFlatFileWizard.start(testProvider);

View File

@@ -6,18 +6,17 @@
import * as TypeMoq from 'typemoq';
import * as azdata from 'azdata';
import { FlatFileWizard } from '../../../wizard/flatFileWizard';
import { ApiWrapper } from '../../../common/apiWrapper';
import { ImportDataModel } from '../../../wizard/api/models';
import { TestImportDataModel, TestQueryProvider } from '../../utils.test';
import { FileConfigPage } from '../../../wizard/pages/fileConfigPage';
import * as should from 'should';
import * as sinon from 'sinon';
import { ImportPage } from '../../../wizard/api/importPage';
import * as constants from '../../../common/constants';
describe('File config page', function () {
let mockFlatFileWizard: TypeMoq.IMock<FlatFileWizard>;
let mockApiWrapper: TypeMoq.IMock<ApiWrapper>;
let mockImportModel: TypeMoq.IMock<ImportDataModel>;
let fileConfigPage: FileConfigPage;
@@ -26,15 +25,15 @@ describe('File config page', function () {
let pages: Map<number, ImportPage> = new Map<number, ImportPage>();
this.beforeEach(function () {
mockApiWrapper = TypeMoq.Mock.ofType(ApiWrapper);
mockFlatFileWizard = TypeMoq.Mock.ofType(FlatFileWizard, TypeMoq.MockBehavior.Loose, undefined, TypeMoq.It.isAny(), mockApiWrapper.object);
mockFlatFileWizard = TypeMoq.Mock.ofType(FlatFileWizard, TypeMoq.MockBehavior.Loose, undefined, TypeMoq.It.isAny());
mockImportModel = TypeMoq.Mock.ofType(TestImportDataModel, TypeMoq.MockBehavior.Loose);
// using the actual vscode and azdata apis.
mockApiWrapper.callBase = true;
wizard = azdata.window.createWizard(constants.wizardNameText);
page = azdata.window.createWizardPage(constants.page1NameText);
});
wizard = mockApiWrapper.object.createWizard(constants.wizardNameText);
page = mockApiWrapper.object.createWizardPage(constants.page1NameText);
afterEach(function (): void {
sinon.restore();
});
it('getSchema returns active schema first', async function () {
@@ -77,9 +76,9 @@ describe('File config page', function () {
// setting up mocks to return test objects created earlier
mockQueryProvider.setup(x => x.runQueryAndReturn(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(async () => { return schemaQueryResult; });
mockApiWrapper.setup(x => x.getProvider<azdata.QueryProvider>(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => { return mockQueryProvider.object; });
sinon.stub(azdata.dataprotocol, 'getProvider' ).returns(mockQueryProvider.object);
let fileConfigPage = new FileConfigPage(mockFlatFileWizard.object, TypeMoq.It.isAny(), mockImportModel.object, TypeMoq.It.isAny(), TypeMoq.It.isAny(), mockApiWrapper.object);
let fileConfigPage = new FileConfigPage(mockFlatFileWizard.object, TypeMoq.It.isAny(), mockImportModel.object, TypeMoq.It.isAny(), TypeMoq.It.isAny());
let actualSchemaValues = await fileConfigPage.getSchemaValues();
should(expectedSchemaValues).deepEqual(actualSchemaValues);
@@ -89,7 +88,7 @@ describe('File config page', function () {
await new Promise(function (resolve) {
page.registerContent(async (view) => {
fileConfigPage = new FileConfigPage(mockFlatFileWizard.object, page, mockImportModel.object, view, TypeMoq.It.isAny(), mockApiWrapper.object);
fileConfigPage = new FileConfigPage(mockFlatFileWizard.object, page, mockImportModel.object, view, TypeMoq.It.isAny());
pages.set(1, fileConfigPage);
await fileConfigPage.start();
resolve();
@@ -118,11 +117,8 @@ describe('File config page', function () {
it('Dropdown values are correctly set', async function () {
// using the actual vscode and azdata apis.
mockApiWrapper.callBase = true;
wizard = mockApiWrapper.object.createWizard(constants.wizardNameText);
page = mockApiWrapper.object.createWizardPage(constants.page1NameText);
wizard = azdata.window.createWizard(constants.wizardNameText);
page = azdata.window.createWizardPage(constants.page1NameText);
// creating mock server values
let testActiveConnections: azdata.connection.Connection[] = [
@@ -154,7 +150,7 @@ describe('File config page', function () {
}
}
];
mockApiWrapper.setup(x => x.getActiveConnections()).returns(async () => { return testActiveConnections; });
sinon.stub(azdata.connection, 'getActiveConnections').returns(Promise.resolve(testActiveConnections));
// creating a test active connection. This connection will be the first value in server dropdown array
let testServerConnection: azdata.connection.Connection = {
@@ -191,7 +187,7 @@ describe('File config page', function () {
// creating mock database values
let databases: string[] = ['testdb1', 'testdb2', 'testdb3'];
mockApiWrapper.setup(x => x.listDatabases(TypeMoq.It.isAnyString())).returns(async () => { return databases; });
sinon.stub(azdata.connection, 'listDatabases').returns(Promise.resolve(databases));
mockImportModel.object.database = 'testdb2';
// expected values for the database dropdown
@@ -236,12 +232,12 @@ describe('File config page', function () {
];
let mockQueryProvider = TypeMoq.Mock.ofType(TestQueryProvider);
mockApiWrapper.setup(x => x.getProvider(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => { return mockQueryProvider.object; });
sinon.stub(azdata.dataprotocol, 'getProvider').returns(mockQueryProvider.object);
mockQueryProvider.setup(x => x.runQueryAndReturn(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(async () => { return schemaQueryResult; });
await new Promise(function (resolve) {
page.registerContent(async (view) => {
fileConfigPage = new FileConfigPage(mockFlatFileWizard.object, page, mockImportModel.object, view, TypeMoq.It.isAny(), mockApiWrapper.object);
fileConfigPage = new FileConfigPage(mockFlatFileWizard.object, page, mockImportModel.object, view, TypeMoq.It.isAny());
pages.set(1, fileConfigPage);
await fileConfigPage.start();
await fileConfigPage.setupNavigationValidator();

View File

@@ -5,7 +5,6 @@
import * as TypeMoq from 'typemoq';
import * as azdata from 'azdata';
import { ApiWrapper } from '../../../common/apiWrapper';
import * as constants from '../../../common/constants';
import { FlatFileWizard } from '../../../wizard/flatFileWizard';
import * as should from 'should';
@@ -21,21 +20,17 @@ describe('import extension modify Column Page', function () {
let modifyColumnsPage: ModifyColumnsPage;
let mockFlatFileWizard: TypeMoq.IMock<FlatFileWizard>;
let mockImportModel: TypeMoq.IMock<ImportDataModel>;
let mockApiWrapper: TypeMoq.IMock<ApiWrapper>;
let pages: Map<number, ImportPage> = new Map<number, ImportPage>();
let mockFlatFileProvider: TypeMoq.IMock<FlatFileProvider>;
beforeEach(function () {
// Keeping the original behaviour of apiWrapper until some setup is needed to mock stuff
mockApiWrapper = TypeMoq.Mock.ofType(ApiWrapper, TypeMoq.MockBehavior.Loose);
mockApiWrapper.callBase = true;
mockFlatFileProvider = TypeMoq.Mock.ofType(TestFlatFileProvider);
mockFlatFileWizard = TypeMoq.Mock.ofType(FlatFileWizard, TypeMoq.MockBehavior.Loose, undefined, mockFlatFileProvider.object, mockApiWrapper.object);
mockFlatFileWizard = TypeMoq.Mock.ofType(FlatFileWizard, TypeMoq.MockBehavior.Loose, undefined, mockFlatFileProvider.object);
mockImportModel = TypeMoq.Mock.ofType(TestImportDataModel, TypeMoq.MockBehavior.Loose);
wizard = mockApiWrapper.object.createWizard(constants.wizardNameText);
page = mockApiWrapper.object.createWizardPage(constants.page3NameText);
wizard = azdata.window.createWizard(constants.wizardNameText);
page = azdata.window.createWizardPage(constants.page3NameText);
});
@@ -43,7 +38,7 @@ describe('import extension modify Column Page', function () {
await new Promise(function (resolve) {
page.registerContent(async (view) => {
modifyColumnsPage = new ModifyColumnsPage(mockFlatFileWizard.object, page, mockImportModel.object, view, TypeMoq.It.isAny(), mockApiWrapper.object);
modifyColumnsPage = new ModifyColumnsPage(mockFlatFileWizard.object, page, mockImportModel.object, view, TypeMoq.It.isAny());
pages.set(1, modifyColumnsPage);
await modifyColumnsPage.start();
resolve();
@@ -88,7 +83,7 @@ describe('import extension modify Column Page', function () {
await new Promise(function (resolve) {
page.registerContent(async (view) => {
modifyColumnsPage = new ModifyColumnsPage(mockFlatFileWizard.object, page, mockImportModel.object, view, TypeMoq.It.isAny(), mockApiWrapper.object);
modifyColumnsPage = new ModifyColumnsPage(mockFlatFileWizard.object, page, mockImportModel.object, view, TypeMoq.It.isAny());
pages.set(1, modifyColumnsPage);
await modifyColumnsPage.start();
resolve();

View File

@@ -5,7 +5,6 @@
import * as TypeMoq from 'typemoq';
import * as azdata from 'azdata';
import { ApiWrapper } from '../../../common/apiWrapper';
import * as constants from '../../../common/constants';
import { FlatFileWizard } from '../../../wizard/flatFileWizard';
import * as should from 'should';
@@ -19,7 +18,6 @@ describe('import extension prose preview tests', function () {
// declaring mock variables
let mockFlatFileWizard: TypeMoq.IMock<FlatFileWizard>;
let mockImportModel: TypeMoq.IMock<ImportDataModel>;
let mockApiWrapper: TypeMoq.IMock<ApiWrapper>;
// declaring instance variables
let wizard: azdata.window.Wizard;
@@ -31,16 +29,12 @@ describe('import extension prose preview tests', function () {
beforeEach(async function () {
// initializing mock variables
mockApiWrapper = TypeMoq.Mock.ofType(ApiWrapper);
mockFlatFileWizard = TypeMoq.Mock.ofType(FlatFileWizard, TypeMoq.MockBehavior.Loose, undefined, TypeMoq.It.isAny(), mockApiWrapper);
mockFlatFileWizard = TypeMoq.Mock.ofType(FlatFileWizard, TypeMoq.MockBehavior.Loose, undefined, TypeMoq.It.isAny());
mockImportModel = TypeMoq.Mock.ofType(TestImportDataModel, TypeMoq.MockBehavior.Loose);
// using the actual vscode and azdata apis.
mockApiWrapper.callBase = true;
// creating a wizard and adding page that will contain the fileConfigPage
wizard = mockApiWrapper.object.createWizard(constants.wizardNameText);
page = mockApiWrapper.object.createWizardPage(constants.page2NameText);
wizard = azdata.window.createWizard(constants.wizardNameText);
page = azdata.window.createWizardPage(constants.page2NameText);
});
@@ -49,7 +43,7 @@ describe('import extension prose preview tests', function () {
// Opening the wizard and initializing the page as ProsePreviewPage
await new Promise(function (resolve) {
page.registerContent(async (view) => {
prosePreviewPage = new ProsePreviewPage(mockFlatFileWizard.object, page, mockImportModel.object, view, TypeMoq.It.isAny(), mockApiWrapper.object);
prosePreviewPage = new ProsePreviewPage(mockFlatFileWizard.object, page, mockImportModel.object, view, TypeMoq.It.isAny());
pages.set(1, prosePreviewPage);
await prosePreviewPage.start();
await prosePreviewPage.setupNavigationValidator();

View File

@@ -5,7 +5,6 @@
import * as TypeMoq from 'typemoq';
import * as azdata from 'azdata';
import { ApiWrapper } from '../../../common/apiWrapper';
import * as constants from '../../../common/constants';
import { FlatFileWizard } from '../../../wizard/flatFileWizard';
import * as should from 'should';
@@ -19,7 +18,6 @@ describe('import extension summary page tests', function () {
let mockFlatFileWizard: TypeMoq.IMock<FlatFileWizard>;
let mockImportModel: TypeMoq.IMock<ImportDataModel>;
let mockApiWrapper: TypeMoq.IMock<ApiWrapper>;
let mockFlatFileProvider: TypeMoq.IMock<FlatFileProvider>;
let summaryPage: SummaryPage;
@@ -28,16 +26,13 @@ describe('import extension summary page tests', function () {
let pages: Map<number, ImportPage> = new Map<number, ImportPage>();
beforeEach(async function () {
// Keeping the original behaviour of apiWrapper until some setup is needed to mock stuff
mockApiWrapper = TypeMoq.Mock.ofType(ApiWrapper, TypeMoq.MockBehavior.Loose);
mockApiWrapper.callBase = true;
mockFlatFileProvider = TypeMoq.Mock.ofType(TestFlatFileProvider);
mockFlatFileWizard = TypeMoq.Mock.ofType(FlatFileWizard, TypeMoq.MockBehavior.Loose, undefined, mockFlatFileProvider.object, mockApiWrapper.object);
mockFlatFileWizard = TypeMoq.Mock.ofType(FlatFileWizard, TypeMoq.MockBehavior.Loose, undefined, mockFlatFileProvider.object);
mockImportModel = TypeMoq.Mock.ofType(TestImportDataModel, TypeMoq.MockBehavior.Loose);
wizard = mockApiWrapper.object.createWizard(constants.wizardNameText);
page = mockApiWrapper.object.createWizardPage(constants.page4NameText);
wizard = azdata.window.createWizard(constants.wizardNameText);
page = azdata.window.createWizardPage(constants.page4NameText);
});
@@ -45,7 +40,7 @@ describe('import extension summary page tests', function () {
await new Promise(function (resolve) {
page.registerContent(async (view) => {
summaryPage = new SummaryPage(mockFlatFileWizard.object, page, mockImportModel.object, view, TypeMoq.It.isAny(), mockApiWrapper.object);
summaryPage = new SummaryPage(mockFlatFileWizard.object, page, mockImportModel.object, view, TypeMoq.It.isAny());
pages.set(1, summaryPage);
await summaryPage.start();
resolve();
@@ -112,7 +107,7 @@ describe('import extension summary page tests', function () {
await new Promise(function (resolve) {
page.registerContent(async (view) => {
summaryPage = new SummaryPage(mockFlatFileWizard.object, page, mockImportModel.object, view, mockFlatFileProvider.object, mockApiWrapper.object);
summaryPage = new SummaryPage(mockFlatFileWizard.object, page, mockImportModel.object, view, mockFlatFileProvider.object);
pages.set(1, summaryPage);
await summaryPage.start();
summaryPage.setupNavigationValidator();

View File

@@ -5,14 +5,12 @@
import * as azdata from 'azdata';
import { ImportDataModel } from './models';
import { ApiWrapper } from '../../common/apiWrapper';
export abstract class BasePage {
protected readonly wizardPage: azdata.window.WizardPage;
protected readonly model: ImportDataModel;
protected readonly view: azdata.ModelView;
protected _apiWrapper: ApiWrapper;
/**
* This method constructs all the elements of the page.
@@ -45,7 +43,7 @@ export abstract class BasePage {
public abstract setupNavigationValidator(): void;
public async getServerValues(): Promise<{ connection: azdata.connection.Connection, displayName: string, name: string }[]> {
let cons = await this._apiWrapper.getActiveConnections();
let cons = await azdata.connection.getActiveConnections();
// This user has no active connections ABORT MISSION
if (!cons || cons.length === 0) {
return undefined;
@@ -95,7 +93,7 @@ export abstract class BasePage {
public async getDatabaseValues(): Promise<{ displayName: string, name: string }[]> {
let idx = -1;
let count = -1;
let values = (await this._apiWrapper.listDatabases(this.model.server.connectionId)).map(db => {
let values = (await azdata.connection.listDatabases(this.model.server.connectionId)).map(db => {
count++;
if (this.model.database && db === this.model.database) {
idx = count;

View File

@@ -8,7 +8,6 @@ import * as azdata from 'azdata';
import { FlatFileProvider } from '../../services/contracts';
import { FlatFileWizard } from '../flatFileWizard';
import { BasePage } from './basePage';
import { ApiWrapper } from '../../common/apiWrapper';
export abstract class ImportPage extends BasePage {
@@ -19,13 +18,12 @@ export abstract class ImportPage extends BasePage {
protected readonly provider: FlatFileProvider;
constructor(instance: FlatFileWizard, wizardPage: azdata.window.WizardPage, model: ImportDataModel, view: azdata.ModelView, provider: FlatFileProvider, apiWrapper: ApiWrapper) {
constructor(instance: FlatFileWizard, wizardPage: azdata.window.WizardPage, model: ImportDataModel, view: azdata.ModelView, provider: FlatFileProvider) {
super();
this.instance = instance;
this.wizardPage = wizardPage;
this.model = model;
this.view = view;
this.provider = provider;
this._apiWrapper = apiWrapper;
}
}

View File

@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import * as vscode from 'vscode';
import { FlatFileProvider } from '../services/contracts';
import { ImportDataModel } from './api/models';
import { ImportPage } from './api/importPage';
@@ -12,7 +13,6 @@ import { FileConfigPage } from './pages/fileConfigPage';
import { ProsePreviewPage } from './pages/prosePreviewPage';
import { ModifyColumnsPage } from './pages/modifyColumnsPage';
import { SummaryPage } from './pages/summaryPage';
import { ApiWrapper } from '../common/apiWrapper';
import * as constants from '../common/constants';
export class FlatFileWizard {
@@ -27,7 +27,6 @@ export class FlatFileWizard {
constructor(
provider: FlatFileProvider,
private _apiWrapper: ApiWrapper
) {
this.provider = provider;
}
@@ -51,16 +50,16 @@ export class FlatFileWizard {
model.serverId = connectionId;
this.wizard = this._apiWrapper.createWizard(constants.wizardNameText);
this.page1 = this._apiWrapper.createWizardPage(constants.page1NameText);
this.page2 = this._apiWrapper.createWizardPage(constants.page2NameText);
this.page3 = this._apiWrapper.createWizardPage(constants.page3NameText);
this.page4 = this._apiWrapper.createWizardPage(constants.page4NameText);
this.wizard = azdata.window.createWizard(constants.wizardNameText);
this.page1 = azdata.window.createWizardPage(constants.page1NameText);
this.page2 = azdata.window.createWizardPage(constants.page2NameText);
this.page3 = azdata.window.createWizardPage(constants.page3NameText);
this.page4 = azdata.window.createWizardPage(constants.page4NameText);
let fileConfigPage: FileConfigPage;
this.page1.registerContent(async (view) => {
fileConfigPage = new FileConfigPage(this, this.page1, model, view, this.provider, this._apiWrapper);
fileConfigPage = new FileConfigPage(this, this.page1, model, view, this.provider);
pages.set(0, fileConfigPage);
await fileConfigPage.start().then(() => {
fileConfigPage.setupNavigationValidator();
@@ -70,14 +69,14 @@ export class FlatFileWizard {
let prosePreviewPage: ProsePreviewPage;
this.page2.registerContent(async (view) => {
prosePreviewPage = new ProsePreviewPage(this, this.page2, model, view, this.provider, this._apiWrapper);
prosePreviewPage = new ProsePreviewPage(this, this.page2, model, view, this.provider);
pages.set(1, prosePreviewPage);
await prosePreviewPage.start();
});
let modifyColumnsPage: ModifyColumnsPage;
this.page3.registerContent(async (view) => {
modifyColumnsPage = new ModifyColumnsPage(this, this.page3, model, view, this.provider, this._apiWrapper);
modifyColumnsPage = new ModifyColumnsPage(this, this.page3, model, view, this.provider);
pages.set(2, modifyColumnsPage);
await modifyColumnsPage.start();
});
@@ -85,13 +84,13 @@ export class FlatFileWizard {
let summaryPage: SummaryPage;
this.page4.registerContent(async (view) => {
summaryPage = new SummaryPage(this, this.page4, model, view, this.provider, this._apiWrapper);
summaryPage = new SummaryPage(this, this.page4, model, view, this.provider);
pages.set(3, summaryPage);
await summaryPage.start();
});
this.importAnotherFileButton = this._apiWrapper.createButton(constants.importNewFileText);
this.importAnotherFileButton = azdata.window.createButton(constants.importNewFileText);
this.importAnotherFileButton.onClick(() => {
//TODO replace this with proper cleanup for all the pages
this.wizard.close();
@@ -124,20 +123,20 @@ export class FlatFileWizard {
}
public async getConnectionId(): Promise<string> {
let currentConnection = await this._apiWrapper.getCurrentConnection();
let currentConnection = await azdata.connection.getCurrentConnection();
let connectionId: string;
if (!currentConnection) {
let connection = await this._apiWrapper.openConnectionDialog(constants.supportedProviders);
let connection = await azdata.connection.openConnectionDialog(constants.supportedProviders);
if (!connection) {
this._apiWrapper.showErrorMessage(constants.needConnectionText);
vscode.window.showErrorMessage(constants.needConnectionText);
return undefined;
}
connectionId = connection.connectionId;
} else {
if (currentConnection.providerId !== 'MSSQL') {
this._apiWrapper.showErrorMessage(constants.needSqlConnectionText);
vscode.window.showErrorMessage(constants.needSqlConnectionText);
return undefined;
}
connectionId = currentConnection.connectionId;

View File

@@ -188,8 +188,8 @@ export class FileConfigPage extends ImportPage {
this.databaseDropdown.onValueChanged(async (db) => {
this.model.database = (<azdata.CategoryValue>this.databaseDropdown.value).name;
//this.populateTableNames();
let connectionProvider = this._apiWrapper.getProvider<azdata.ConnectionProvider>(this.model.server.providerName, azdata.DataProviderType.ConnectionProvider);
let connectionUri = await this._apiWrapper.getUriForConnection(this.model.server.connectionId);
let connectionProvider = azdata.dataprotocol.getProvider<azdata.ConnectionProvider>(this.model.server.providerName, azdata.DataProviderType.ConnectionProvider);
let connectionUri = await azdata.connection.getUriForConnection(this.model.server.connectionId);
connectionProvider.changeDatabase(connectionUri, this.model.database);
this.populateSchemaDropdown();
});
@@ -372,8 +372,8 @@ export class FileConfigPage extends ImportPage {
}
public async getSchemaValues(): Promise<{ displayName: string, name: string }[]> {
let connectionUri = await this._apiWrapper.getUriForConnection(this.model.server.connectionId);
let queryProvider = this._apiWrapper.getProvider<azdata.QueryProvider>(this.model.server.providerName, azdata.DataProviderType.QueryProvider);
let connectionUri = await azdata.connection.getUriForConnection(this.model.server.connectionId);
let queryProvider = azdata.dataprotocol.getProvider<azdata.QueryProvider>(this.model.server.providerName, azdata.DataProviderType.QueryProvider);
let results = await queryProvider.runQueryAndReturn(connectionUri, constants.selectSchemaQuery);

View File

@@ -123,7 +123,7 @@ export class SummaryPage extends ImportPage {
try {
result = await this.provider.sendInsertDataRequest({
connectionString: await this._apiWrapper.getConnectionString(this.model.server.connectionId, includePasswordInConnectionString),
connectionString: await azdata.connection.getConnectionString(this.model.server.connectionId, includePasswordInConnectionString),
//TODO check what SSMS uses as batch size
batchSize: 500
});