mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-09 09:42:34 -05:00
Additional tests for the import wizard (#11273)
* Setting up tests on import extension * -Added API wrappers for all the azdata and vscode APIs to make them easily mockable -Added some unit tests for the import extension -Some code logic separations * -added code report for the import extension in ci * Did some more code refractoring * -Added json report generation * updated vscodetestcoverage to latest version in import extension. * -remove duplicate codecoverageConfig.json * -Added some modifyColumnPage tests * pushing temp changes * -Added some more testcases * -Added tests using available vscode and azdata apis * some minor comment change * removed unnecessary test * added accidently removed test * Added some comments * fixed some broken tests and added comments in fileConfigPage * code clean up and some more comments * fixed the prosePreviewPage test and the download test * added getter and setters * Increasing timeout and fixing a comment * removed unnecessary comments and some other code cleanup * Deleting dotnet files before redownloading them * - made changes in the PR - Moved extensioncode to utils.test for better reusability * added some 'should' messages
This commit is contained in:
@@ -12,6 +12,8 @@ export const configLogDebugInfo = 'logDebugInfo';
|
||||
export const sqlConfigSectionName = 'sql';
|
||||
export const mssqlProvider = 'MSSQL';
|
||||
|
||||
export const summaryErrorSymbol = '✗ ';
|
||||
|
||||
export const supportedProviders = [mssqlProvider];
|
||||
|
||||
// Links
|
||||
|
||||
@@ -3,29 +3,42 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as TypeMoq from 'typemoq';
|
||||
import { ApiWrapper } from '../../common/apiWrapper';
|
||||
import MainController from '../../controllers/mainController';
|
||||
import { TestExtensionContext } from '../utils.test';
|
||||
import * as constants from '../../common/constants';
|
||||
import * as should from 'should';
|
||||
import * as path from 'path';
|
||||
import { ImportTestUtils, TestExtensionContext } from '../utils.test';
|
||||
|
||||
describe('Main Controller', function () {
|
||||
let mockExtensionContext: TypeMoq.IMock<vscode.ExtensionContext>;
|
||||
let testExtensionContext: TestExtensionContext;
|
||||
let mockApiWrapper: TypeMoq.IMock<ApiWrapper>;
|
||||
let extensionPath: string;
|
||||
|
||||
this.beforeEach(function () {
|
||||
mockExtensionContext = TypeMoq.Mock.ofType(TestExtensionContext, TypeMoq.MockBehavior.Loose);
|
||||
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 create new instance successfully', async function () {
|
||||
// mocking createOutputChannel in API wrapper
|
||||
mockApiWrapper.setup(x => x.createOutputChannel(TypeMoq.It.isAny()));
|
||||
it('Should download required binaries and register flatFileImportStartCommand after activate is called', async function () {
|
||||
this.timeout(50000);
|
||||
|
||||
// creating a Main Controller
|
||||
new MainController(mockExtensionContext.object, mockApiWrapper.object);
|
||||
|
||||
// verifying if the output channel is created
|
||||
mockApiWrapper.verify(x => x.createOutputChannel(TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||
// 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);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -16,4 +16,3 @@ describe('Service utitlities test', function () {
|
||||
should(ensure({ 'testkey': 'testval' }, 'testkey')).equal('testval');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
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 {
|
||||
|
||||
@@ -34,6 +36,22 @@ export class ImportTestUtils {
|
||||
options: {}
|
||||
} 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;
|
||||
}
|
||||
|
||||
public static async getTestExtensionContext(): Promise<TestExtensionContext> {
|
||||
let testContext = new TestExtensionContext();
|
||||
testContext.extensionPath = await vscode.extensions.getExtension('Microsoft.import').extensionPath;
|
||||
return testContext;
|
||||
}
|
||||
}
|
||||
|
||||
export class TestQueryProvider implements azdata.QueryProvider {
|
||||
@@ -211,3 +229,20 @@ export class TestImportDataModel implements ImportDataModel {
|
||||
filePath: string;
|
||||
fileType: string;
|
||||
}
|
||||
|
||||
export class TestFlatFileProvider implements FlatFileProvider {
|
||||
providerId?: string;
|
||||
sendPROSEDiscoveryRequest(params: PROSEDiscoveryParams): Thenable<PROSEDiscoveryResponse> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
sendInsertDataRequest(params: InsertDataParams): Thenable<InsertDataResponse> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
sendGetColumnInfoRequest(params: GetColumnInfoParams): Thenable<GetColumnInfoResponse> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
sendChangeColumnSettingsRequest(params: ChangeColumnSettingsParams): Thenable<ChangeColumnSettingsResponse> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ describe('import extension wizard pages', function () {
|
||||
let mockApiWrapper: TypeMoq.IMock<ApiWrapper>;
|
||||
let mockImportModel: TypeMoq.IMock<ImportDataModel>;
|
||||
|
||||
this.beforeEach(function () {
|
||||
beforeEach(function () {
|
||||
mockApiWrapper = TypeMoq.Mock.ofType(ApiWrapper);
|
||||
mockFlatFileWizard = TypeMoq.Mock.ofType(FlatFileWizard, TypeMoq.MockBehavior.Loose, undefined, TypeMoq.It.isAny(), mockApiWrapper.object);
|
||||
mockImportModel = TypeMoq.Mock.ofType(TestImportDataModel, TypeMoq.MockBehavior.Loose);
|
||||
@@ -59,13 +59,16 @@ describe('import extension wizard pages', function () {
|
||||
|
||||
let serverValues = await importPage.getServerValues();
|
||||
|
||||
should(serverValues).undefined();
|
||||
// getServer should be undefined for null active connections
|
||||
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[]; });
|
||||
|
||||
serverValues = await importPage.getServerValues();
|
||||
should(serverValues).undefined();
|
||||
|
||||
// getServer should be undefined for empty active connections
|
||||
should.equal(serverValues, undefined, 'getServer should be undefined for empty active conections');
|
||||
});
|
||||
|
||||
it('getServerValue return active server value first', async function () {
|
||||
@@ -101,6 +104,7 @@ describe('import extension wizard pages', function () {
|
||||
mockApiWrapper.setup(x => x.getActiveConnections()).returns(async () => { return testActiveConnections; });
|
||||
mockImportModel.object.server = ImportTestUtils.getTestServer();
|
||||
|
||||
// the second connection should be the first element in the array as it is active
|
||||
let expectedConnectionValues = [
|
||||
{
|
||||
connection: testActiveConnections[1],
|
||||
|
||||
@@ -11,22 +11,37 @@ import { ImportDataModel } from '../../../wizard/api/models';
|
||||
import { TestImportDataModel, TestQueryProvider } from '../../utils.test';
|
||||
import { FileConfigPage } from '../../../wizard/pages/fileConfigPage';
|
||||
import * as should from 'should';
|
||||
import { ImportPage } from '../../../wizard/api/importPage';
|
||||
import * as constants from '../../../common/constants';
|
||||
|
||||
describe('import extension wizard pages', function () {
|
||||
describe('File config page', function () {
|
||||
|
||||
let mockFlatFileWizard: TypeMoq.IMock<FlatFileWizard>;
|
||||
let mockApiWrapper: TypeMoq.IMock<ApiWrapper>;
|
||||
let mockImportModel: TypeMoq.IMock<ImportDataModel>;
|
||||
|
||||
let fileConfigPage: FileConfigPage;
|
||||
let wizard: azdata.window.Wizard;
|
||||
let page: azdata.window.WizardPage;
|
||||
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);
|
||||
mockImportModel = TypeMoq.Mock.ofType(TestImportDataModel, TypeMoq.MockBehavior.Loose);
|
||||
|
||||
// using the actual vscode and azdata apis.
|
||||
mockApiWrapper.callBase = true;
|
||||
|
||||
wizard = mockApiWrapper.object.createWizard(constants.wizardNameText);
|
||||
page = mockApiWrapper.object.createWizardPage(constants.page1NameText);
|
||||
});
|
||||
|
||||
it('get schema returns active schema first', async function () {
|
||||
mockApiWrapper.setup(x => x.getUriForConnection(TypeMoq.It.isAny()));
|
||||
it('getSchema returns active schema first', async function () {
|
||||
|
||||
let mockQueryProvider = TypeMoq.Mock.ofType(TestQueryProvider);
|
||||
|
||||
// mock result for the schema query
|
||||
let schemaQueryResult: azdata.SimpleExecuteResult = {
|
||||
rowCount: 3,
|
||||
rows: [
|
||||
@@ -41,26 +56,211 @@ describe('import extension wizard pages', function () {
|
||||
]
|
||||
],
|
||||
columnInfo: undefined
|
||||
}
|
||||
};
|
||||
|
||||
// setting the default schema for the current connection. This schema should be the first value in the dropdown array
|
||||
mockImportModel.object.schema = 'schema2';
|
||||
|
||||
// expected schema values for the dropdown that will be created
|
||||
let expectedSchemaValues = [
|
||||
{ displayName: 'schema2', name: 'schema2' }, // This should be the first database as it is active in the extension.
|
||||
{ displayName: 'schema1', name: 'schema1' },
|
||||
{ displayName: 'schema3', name: 'schema3' }
|
||||
];
|
||||
|
||||
mockImportModel.object.schema = 'schema2';
|
||||
// creating a mock connection
|
||||
mockImportModel.object.server = {
|
||||
providerName: 'MSSQL',
|
||||
connectionId: 'testConnectionId',
|
||||
options: {}
|
||||
};
|
||||
mockQueryProvider.setup(x => x.runQueryAndReturn(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(async () => { return schemaQueryResult });
|
||||
|
||||
// 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; });
|
||||
|
||||
let importPage = new FileConfigPage(mockFlatFileWizard.object, TypeMoq.It.isAny(), mockImportModel.object, TypeMoq.It.isAny(), TypeMoq.It.isAny(), mockApiWrapper.object);
|
||||
let actualSchemaValues = await importPage.getSchemaValues();
|
||||
let fileConfigPage = new FileConfigPage(mockFlatFileWizard.object, TypeMoq.It.isAny(), mockImportModel.object, TypeMoq.It.isAny(), TypeMoq.It.isAny(), mockApiWrapper.object);
|
||||
let actualSchemaValues = await fileConfigPage.getSchemaValues();
|
||||
|
||||
should(expectedSchemaValues).deepEqual(actualSchemaValues);
|
||||
});
|
||||
|
||||
it('checking if all components are initialized properly', async function () {
|
||||
|
||||
await new Promise(function (resolve) {
|
||||
page.registerContent(async (view) => {
|
||||
fileConfigPage = new FileConfigPage(mockFlatFileWizard.object, page, mockImportModel.object, view, TypeMoq.It.isAny(), mockApiWrapper.object);
|
||||
pages.set(1, fileConfigPage);
|
||||
await fileConfigPage.start();
|
||||
resolve();
|
||||
|
||||
});
|
||||
wizard.generateScriptButton.hidden = true;
|
||||
|
||||
wizard.pages = [page];
|
||||
wizard.open();
|
||||
});
|
||||
|
||||
// checking if all the required components are correctly initialized
|
||||
should.notEqual(fileConfigPage.serverDropdown, undefined, 'serverDropdown should not be undefined');
|
||||
should.notEqual(fileConfigPage.databaseDropdown, undefined, 'databaseDropdown should not be undefined');
|
||||
should.notEqual(fileConfigPage.fileTextBox, undefined, 'fileTextBox should not be undefined');
|
||||
should.notEqual(fileConfigPage.fileButton, undefined, 'fileButton should not be undefined');
|
||||
should.notEqual(fileConfigPage.tableNameTextBox, undefined, 'tableNameTextBox should not be undefined');
|
||||
should.notEqual(fileConfigPage.schemaDropdown, undefined, 'schemaDropdown should not be undefined');
|
||||
should.notEqual(fileConfigPage.form, undefined, 'form should not be undefined');
|
||||
should.notEqual(fileConfigPage.databaseLoader, undefined, 'databaseLoader should not be undefined');
|
||||
should.notEqual(fileConfigPage.schemaLoader, undefined, 'schemaLoader should not be undefined');
|
||||
|
||||
await fileConfigPage.onPageLeave();
|
||||
await fileConfigPage.cleanup();
|
||||
});
|
||||
|
||||
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);
|
||||
|
||||
// creating mock server values
|
||||
let testActiveConnections: azdata.connection.Connection[] = [
|
||||
{
|
||||
providerName: 'MSSQL',
|
||||
connectionId: 'testConnection1Id',
|
||||
options: {
|
||||
user: 'testcon1user',
|
||||
server: 'testcon1server',
|
||||
database: 'testdb1'
|
||||
}
|
||||
},
|
||||
{
|
||||
providerName: 'MSSQL',
|
||||
connectionId: 'testConnection2Id',
|
||||
options: {
|
||||
user: 'testcon2user',
|
||||
server: 'testcon2server',
|
||||
database: 'testdb2'
|
||||
}
|
||||
},
|
||||
{
|
||||
providerName: 'PGSQL',
|
||||
connectionId: 'testConnection3Id',
|
||||
options: {
|
||||
user: undefined, // setting it undefined to check if function return user as 'default
|
||||
server: 'testcon3server',
|
||||
database: 'testdb3'
|
||||
}
|
||||
}
|
||||
];
|
||||
mockApiWrapper.setup(x => x.getActiveConnections()).returns(async () => { return testActiveConnections; });
|
||||
|
||||
// creating a test active connection. This connection will be the first value in server dropdown array
|
||||
let testServerConnection: azdata.connection.Connection = {
|
||||
providerName: 'MSSQL',
|
||||
connectionId: 'testConnection2Id',
|
||||
options: {
|
||||
// default database. This datatabe will be the first value in the database dropdown
|
||||
database: 'testdb2',
|
||||
user: 'testcon2user',
|
||||
server: 'testcon2server'
|
||||
}
|
||||
};
|
||||
mockImportModel.object.server = testServerConnection;
|
||||
mockImportModel.object.server.options = testServerConnection.options;
|
||||
|
||||
// expected values for the server dropdown
|
||||
let expectedConnectionValues = [
|
||||
{
|
||||
connection: testActiveConnections[1],
|
||||
displayName: 'testcon2server (testcon2user)',
|
||||
name: 'testConnection2Id'
|
||||
},
|
||||
{
|
||||
connection: testActiveConnections[0],
|
||||
displayName: 'testcon1server (testcon1user)',
|
||||
name: 'testConnection1Id'
|
||||
},
|
||||
{
|
||||
connection: testActiveConnections[2],
|
||||
displayName: 'testcon3server (default)',
|
||||
name: 'testConnection3Id'
|
||||
}
|
||||
];
|
||||
|
||||
// creating mock database values
|
||||
let databases: string[] = ['testdb1', 'testdb2', 'testdb3'];
|
||||
mockApiWrapper.setup(x => x.listDatabases(TypeMoq.It.isAnyString())).returns(async () => { return databases; });
|
||||
mockImportModel.object.database = 'testdb2';
|
||||
|
||||
// expected values for the database dropdown
|
||||
let expectedDatabaseDropdownValues = [
|
||||
{
|
||||
displayName: 'testdb2',
|
||||
name: 'testdb2'
|
||||
},
|
||||
{
|
||||
displayName: 'testdb1',
|
||||
name: 'testdb1'
|
||||
},
|
||||
{
|
||||
displayName: 'testdb3',
|
||||
name: 'testdb3'
|
||||
}
|
||||
];
|
||||
|
||||
// mock result for the schema query
|
||||
let schemaQueryResult: azdata.SimpleExecuteResult = {
|
||||
rowCount: 3,
|
||||
rows: [
|
||||
[
|
||||
{ displayValue: 'schema1', isNull: false, invariantCultureDisplayValue: 'schema1' }
|
||||
],
|
||||
[
|
||||
{ displayValue: 'schema2', isNull: false, invariantCultureDisplayValue: 'schema2' }
|
||||
],
|
||||
[
|
||||
{ displayValue: 'schema3', isNull: false, invariantCultureDisplayValue: 'schema3' }
|
||||
]
|
||||
],
|
||||
columnInfo: undefined
|
||||
};
|
||||
mockImportModel.object.schema = 'schema2';
|
||||
|
||||
// expected values for the schema dropdown
|
||||
let expectedSchemaValues = [
|
||||
{ displayName: 'schema2', name: 'schema2' }, // This should be the first database as it is active in the extension.
|
||||
{ displayName: 'schema1', name: 'schema1' },
|
||||
{ displayName: 'schema3', name: 'schema3' }
|
||||
];
|
||||
|
||||
let mockQueryProvider = TypeMoq.Mock.ofType(TestQueryProvider);
|
||||
mockApiWrapper.setup(x => x.getProvider(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => { return 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);
|
||||
pages.set(1, fileConfigPage);
|
||||
await fileConfigPage.start();
|
||||
await fileConfigPage.setupNavigationValidator();
|
||||
resolve();
|
||||
});
|
||||
wizard.generateScriptButton.hidden = true;
|
||||
|
||||
wizard.pages = [page];
|
||||
wizard.open();
|
||||
});
|
||||
|
||||
|
||||
await fileConfigPage.onPageEnter();
|
||||
|
||||
should.deepEqual(fileConfigPage.serverDropdown.value, expectedConnectionValues[0]);
|
||||
should.deepEqual(fileConfigPage.serverDropdown.values, expectedConnectionValues);
|
||||
should.deepEqual(fileConfigPage.databaseDropdown.value, expectedDatabaseDropdownValues[0]);
|
||||
should.deepEqual(fileConfigPage.databaseDropdown.values, expectedDatabaseDropdownValues);
|
||||
should.deepEqual(fileConfigPage.schemaDropdown.value, expectedSchemaValues[0]);
|
||||
should.deepEqual(fileConfigPage.schemaDropdown.values, expectedSchemaValues);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
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';
|
||||
import { ModifyColumnsPage } from '../../../wizard/pages/modifyColumnsPage';
|
||||
import { ImportDataModel } from '../../../wizard/api/models';
|
||||
import { TestImportDataModel, TestFlatFileProvider } from '../../utils.test';
|
||||
import { ImportPage } from '../../../wizard/api/importPage';
|
||||
import { FlatFileProvider } from '../../../services/contracts';
|
||||
|
||||
describe('import extension modify Column Page', function () {
|
||||
let wizard: azdata.window.Wizard;
|
||||
let page: azdata.window.WizardPage;
|
||||
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);
|
||||
mockImportModel = TypeMoq.Mock.ofType(TestImportDataModel, TypeMoq.MockBehavior.Loose);
|
||||
|
||||
wizard = mockApiWrapper.object.createWizard(constants.wizardNameText);
|
||||
page = mockApiWrapper.object.createWizardPage(constants.page3NameText);
|
||||
|
||||
});
|
||||
|
||||
it('checking if all components are initialized properly', async function () {
|
||||
|
||||
await new Promise(function (resolve) {
|
||||
page.registerContent(async (view) => {
|
||||
modifyColumnsPage = new ModifyColumnsPage(mockFlatFileWizard.object, page, mockImportModel.object, view, TypeMoq.It.isAny(), mockApiWrapper.object);
|
||||
pages.set(1, modifyColumnsPage);
|
||||
await modifyColumnsPage.start();
|
||||
resolve();
|
||||
});
|
||||
wizard.generateScriptButton.hidden = true;
|
||||
|
||||
wizard.pages = [page];
|
||||
wizard.open();
|
||||
});
|
||||
|
||||
// checking if all the components are initialized properly
|
||||
should.notEqual(modifyColumnsPage.table, undefined, 'table should not be undefined');
|
||||
should.notEqual(modifyColumnsPage.text, undefined, 'text should not be undefined');
|
||||
should.notEqual(modifyColumnsPage.loading, undefined, 'loading should not be undefined');
|
||||
should.notEqual(modifyColumnsPage.form, undefined, 'form should not be undefined');
|
||||
});
|
||||
|
||||
it('handleImport updates table value correctly when import is successful', async function() {
|
||||
|
||||
|
||||
let testProseColumns = [
|
||||
{
|
||||
columnName: 'column1',
|
||||
dataType: 'nvarchar(50)',
|
||||
primaryKey: false,
|
||||
nullable: false
|
||||
},
|
||||
{
|
||||
columnName: 'column2',
|
||||
dataType: 'nvarchar(50)',
|
||||
primaryKey: false,
|
||||
nullable: false
|
||||
}
|
||||
];
|
||||
|
||||
let testTableData = [
|
||||
[ 'column1', 'nvarchar(50)', false, false],
|
||||
[ 'column2', 'nvarchar(50)', false, false]
|
||||
];
|
||||
|
||||
mockImportModel.object.proseColumns = testProseColumns;
|
||||
|
||||
await new Promise(function (resolve) {
|
||||
page.registerContent(async (view) => {
|
||||
modifyColumnsPage = new ModifyColumnsPage(mockFlatFileWizard.object, page, mockImportModel.object, view, TypeMoq.It.isAny(), mockApiWrapper.object);
|
||||
pages.set(1, modifyColumnsPage);
|
||||
await modifyColumnsPage.start();
|
||||
resolve();
|
||||
});
|
||||
wizard.generateScriptButton.hidden = true;
|
||||
|
||||
wizard.pages = [page];
|
||||
wizard.open();
|
||||
});
|
||||
|
||||
|
||||
await modifyColumnsPage.onPageEnter();
|
||||
|
||||
// checking if all the required components are correctly initialized
|
||||
should.deepEqual(modifyColumnsPage.table.data, testTableData);
|
||||
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,75 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
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';
|
||||
import { ImportDataModel } from '../../../wizard/api/models';
|
||||
import { TestImportDataModel } from '../../utils.test';
|
||||
import { ImportPage } from '../../../wizard/api/importPage';
|
||||
import { ProsePreviewPage } from '../../../wizard/pages/prosePreviewPage';
|
||||
|
||||
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;
|
||||
let page: azdata.window.WizardPage;
|
||||
let pages: Map<number, ImportPage> = new Map<number, ImportPage>();
|
||||
let prosePreviewPage: ProsePreviewPage;
|
||||
|
||||
|
||||
beforeEach(async function () {
|
||||
|
||||
// initializing mock variables
|
||||
mockApiWrapper = TypeMoq.Mock.ofType(ApiWrapper);
|
||||
mockFlatFileWizard = TypeMoq.Mock.ofType(FlatFileWizard, TypeMoq.MockBehavior.Loose, undefined, TypeMoq.It.isAny(), mockApiWrapper);
|
||||
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);
|
||||
|
||||
});
|
||||
|
||||
it('checking if all components are initialized properly', async 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);
|
||||
pages.set(1, prosePreviewPage);
|
||||
await prosePreviewPage.start();
|
||||
await prosePreviewPage.setupNavigationValidator();
|
||||
await prosePreviewPage.onPageEnter();
|
||||
resolve();
|
||||
});
|
||||
wizard.generateScriptButton.hidden = true;
|
||||
wizard.pages = [page];
|
||||
wizard.open();
|
||||
});
|
||||
|
||||
// checking if all the required components are correctly initialized
|
||||
should.notEqual(prosePreviewPage.table, undefined, 'table should not be undefined');
|
||||
should.notEqual(prosePreviewPage.refresh, undefined, 'refresh should not be undefined');
|
||||
should.notEqual(prosePreviewPage.loading, undefined, 'loading should not be undefined');
|
||||
should.notEqual(prosePreviewPage.form, undefined, 'form should not be undefined');
|
||||
should.notEqual(prosePreviewPage.resultTextComponent, undefined, 'resultTextComponent should not be undefined');
|
||||
|
||||
// calling the clean up code
|
||||
await prosePreviewPage.onPageLeave();
|
||||
await prosePreviewPage.cleanup();
|
||||
});
|
||||
});
|
||||
149
extensions/import/src/test/wizard/pages/summaryPage.test.ts
Normal file
149
extensions/import/src/test/wizard/pages/summaryPage.test.ts
Normal file
@@ -0,0 +1,149 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
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';
|
||||
import { ImportDataModel } from '../../../wizard/api/models';
|
||||
import { TestImportDataModel, TestFlatFileProvider } from '../../utils.test';
|
||||
import { ImportPage } from '../../../wizard/api/importPage';
|
||||
import { SummaryPage } from '../../../wizard/pages/summaryPage';
|
||||
import { FlatFileProvider, InsertDataResponse } from '../../../services/contracts';
|
||||
|
||||
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;
|
||||
let wizard: azdata.window.Wizard;
|
||||
let page: azdata.window.WizardPage;
|
||||
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);
|
||||
mockImportModel = TypeMoq.Mock.ofType(TestImportDataModel, TypeMoq.MockBehavior.Loose);
|
||||
|
||||
wizard = mockApiWrapper.object.createWizard(constants.wizardNameText);
|
||||
page = mockApiWrapper.object.createWizardPage(constants.page4NameText);
|
||||
|
||||
});
|
||||
|
||||
it('checking if all components are initialized properly', async function () {
|
||||
|
||||
await new Promise(function (resolve) {
|
||||
page.registerContent(async (view) => {
|
||||
summaryPage = new SummaryPage(mockFlatFileWizard.object, page, mockImportModel.object, view, TypeMoq.It.isAny(), mockApiWrapper.object);
|
||||
pages.set(1, summaryPage);
|
||||
await summaryPage.start();
|
||||
resolve();
|
||||
|
||||
});
|
||||
wizard.generateScriptButton.hidden = true;
|
||||
|
||||
wizard.pages = [page];
|
||||
wizard.open();
|
||||
});
|
||||
|
||||
// checking if all the required components are correctly initialized
|
||||
should.notEqual(summaryPage.table, undefined, 'table should not be undefined');
|
||||
should.notEqual(summaryPage.statusText, undefined, 'statusText should not be undefined');
|
||||
should.notEqual(summaryPage.loading, undefined, 'loading should not be undefined');
|
||||
should.notEqual(summaryPage.form, undefined, 'form should not be undefined');
|
||||
|
||||
await summaryPage.onPageLeave();
|
||||
await summaryPage.cleanup();
|
||||
|
||||
});
|
||||
|
||||
it('handle import updates status Text correctly', async function () {
|
||||
|
||||
// Creating a test Connection
|
||||
let testServerConnection: azdata.connection.Connection = {
|
||||
providerName: 'testProviderName',
|
||||
connectionId: 'testConnectionId',
|
||||
options: {}
|
||||
};
|
||||
|
||||
|
||||
// setting up connection objects in model
|
||||
mockImportModel.object.server = testServerConnection;
|
||||
mockImportModel.object.database = 'testDatabase';
|
||||
mockImportModel.object.schema = 'testSchema';
|
||||
mockImportModel.object.filePath = 'testFilePath';
|
||||
|
||||
// Creating test columns
|
||||
let testProseColumns = [
|
||||
{
|
||||
columnName: 'column1',
|
||||
dataType: 'nvarchar(50)',
|
||||
primaryKey: false,
|
||||
nullable: false
|
||||
},
|
||||
{
|
||||
columnName: 'column2',
|
||||
dataType: 'nvarchar(50)',
|
||||
primaryKey: false,
|
||||
nullable: false
|
||||
}
|
||||
];
|
||||
mockImportModel.object.proseColumns = testProseColumns;
|
||||
|
||||
// setting up a test table insert response from FlatFileProvider
|
||||
let testSendInsertDataRequestResponse: InsertDataResponse = {
|
||||
result: {
|
||||
success: true,
|
||||
errorMessage: ''
|
||||
}
|
||||
};
|
||||
mockFlatFileProvider.setup(x => x.sendInsertDataRequest(TypeMoq.It.isAny())).returns(async () => { return testSendInsertDataRequestResponse; });
|
||||
|
||||
await new Promise(function (resolve) {
|
||||
page.registerContent(async (view) => {
|
||||
summaryPage = new SummaryPage(mockFlatFileWizard.object, page, mockImportModel.object, view, mockFlatFileProvider.object, mockApiWrapper.object);
|
||||
pages.set(1, summaryPage);
|
||||
await summaryPage.start();
|
||||
summaryPage.setupNavigationValidator();
|
||||
resolve();
|
||||
});
|
||||
wizard.generateScriptButton.hidden = true;
|
||||
|
||||
wizard.pages = [page];
|
||||
wizard.open();
|
||||
});
|
||||
|
||||
// Entering the page. This method will try to create table using FlatFileProvider
|
||||
await summaryPage.onPageEnter();
|
||||
|
||||
// In case of success we should see the success message
|
||||
should.equal(summaryPage.statusText.value, constants.updateText);
|
||||
|
||||
// In case of a failure we should see the error message
|
||||
testSendInsertDataRequestResponse = {
|
||||
result: {
|
||||
success: false,
|
||||
errorMessage: 'testError'
|
||||
}
|
||||
};
|
||||
|
||||
// mocking the insertDataRequest to fail
|
||||
mockFlatFileProvider.setup(x => x.sendInsertDataRequest(TypeMoq.It.isAny())).returns(async () => { return testSendInsertDataRequestResponse; });
|
||||
|
||||
// Entering the page. This method will try to create table using FlatFileProvider
|
||||
await summaryPage.onPageEnter();
|
||||
should.equal(summaryPage.statusText.value, constants.summaryErrorSymbol + 'testError');
|
||||
|
||||
});
|
||||
});
|
||||
@@ -10,16 +10,89 @@ import * as constants from '../../common/constants';
|
||||
|
||||
export class FileConfigPage extends ImportPage {
|
||||
|
||||
private serverDropdown: azdata.DropDownComponent;
|
||||
private databaseDropdown: azdata.DropDownComponent;
|
||||
private fileTextBox: azdata.InputBoxComponent;
|
||||
private fileButton: azdata.ButtonComponent;
|
||||
private tableNameTextBox: azdata.InputBoxComponent;
|
||||
private schemaDropdown: azdata.DropDownComponent;
|
||||
private form: azdata.FormContainer;
|
||||
private _serverDropdown: azdata.DropDownComponent;
|
||||
private _databaseDropdown: azdata.DropDownComponent;
|
||||
private _fileTextBox: azdata.InputBoxComponent;
|
||||
private _fileButton: azdata.ButtonComponent;
|
||||
private _tableNameTextBox: azdata.InputBoxComponent;
|
||||
private _schemaDropdown: azdata.DropDownComponent;
|
||||
private _form: azdata.FormContainer;
|
||||
|
||||
private _databaseLoader: azdata.LoadingComponent;
|
||||
private _schemaLoader: azdata.LoadingComponent;
|
||||
|
||||
public get serverDropdown(): azdata.DropDownComponent {
|
||||
return this._serverDropdown;
|
||||
}
|
||||
|
||||
public set serverDropdown(serverDropdown: azdata.DropDownComponent) {
|
||||
this._serverDropdown = serverDropdown;
|
||||
}
|
||||
|
||||
public get databaseDropdown(): azdata.DropDownComponent {
|
||||
return this._databaseDropdown;
|
||||
}
|
||||
|
||||
public set databaseDropdown(databaseDropdown: azdata.DropDownComponent) {
|
||||
this._databaseDropdown = databaseDropdown;
|
||||
}
|
||||
|
||||
public get fileTextBox(): azdata.InputBoxComponent {
|
||||
return this._fileTextBox;
|
||||
}
|
||||
|
||||
public set fileTextBox(fileTextBox: azdata.InputBoxComponent) {
|
||||
this._fileTextBox = fileTextBox;
|
||||
}
|
||||
|
||||
public get fileButton(): azdata.ButtonComponent {
|
||||
return this._fileButton;
|
||||
}
|
||||
|
||||
public set fileButton(fileButton: azdata.ButtonComponent) {
|
||||
this._fileButton = fileButton;
|
||||
}
|
||||
|
||||
public get tableNameTextBox(): azdata.InputBoxComponent {
|
||||
return this._tableNameTextBox;
|
||||
}
|
||||
|
||||
public set tableNameTextBox(tableNameTextBox: azdata.InputBoxComponent) {
|
||||
this._tableNameTextBox = tableNameTextBox;
|
||||
}
|
||||
|
||||
public get schemaDropdown(): azdata.DropDownComponent {
|
||||
return this._schemaDropdown;
|
||||
}
|
||||
|
||||
public set schemaDropdown(schemaDropdown: azdata.DropDownComponent) {
|
||||
this._schemaDropdown = schemaDropdown;
|
||||
}
|
||||
|
||||
public get form(): azdata.FormContainer {
|
||||
return this._form;
|
||||
}
|
||||
|
||||
public set form(form: azdata.FormContainer) {
|
||||
this._form = form;
|
||||
}
|
||||
|
||||
public get databaseLoader(): azdata.LoadingComponent {
|
||||
return this._databaseLoader;
|
||||
}
|
||||
|
||||
public set databaseLoader(databaseLoader: azdata.LoadingComponent) {
|
||||
this._databaseLoader = databaseLoader;
|
||||
}
|
||||
|
||||
public get schemaLoader(): azdata.LoadingComponent {
|
||||
return this._schemaLoader;
|
||||
}
|
||||
|
||||
public set schemaLoader(schemaLoader: azdata.LoadingComponent) {
|
||||
this._schemaLoader = schemaLoader;
|
||||
}
|
||||
|
||||
private databaseLoader: azdata.LoadingComponent;
|
||||
private schemaLoader: azdata.LoadingComponent;
|
||||
|
||||
private tableNames: string[] = [];
|
||||
|
||||
|
||||
@@ -45,10 +45,43 @@ export class ModifyColumnsPage extends ImportPage {
|
||||
{ name: 'varchar(50)', displayName: 'varchar(50)' },
|
||||
{ name: 'varchar(MAX)', displayName: 'varchar(MAX)' }
|
||||
];
|
||||
private table: azdata.DeclarativeTableComponent;
|
||||
private loading: azdata.LoadingComponent;
|
||||
private text: azdata.TextComponent;
|
||||
private form: azdata.FormContainer;
|
||||
|
||||
private _table: azdata.DeclarativeTableComponent;
|
||||
private _loading: azdata.LoadingComponent;
|
||||
private _text: azdata.TextComponent;
|
||||
private _form: azdata.FormContainer;
|
||||
|
||||
public get table(): azdata.DeclarativeTableComponent {
|
||||
return this._table;
|
||||
}
|
||||
|
||||
public set table(table: azdata.DeclarativeTableComponent) {
|
||||
this._table = table;
|
||||
}
|
||||
|
||||
public get loading(): azdata.LoadingComponent {
|
||||
return this._loading;
|
||||
}
|
||||
|
||||
public set loading(loading: azdata.LoadingComponent) {
|
||||
this._loading = loading;
|
||||
}
|
||||
|
||||
public get text(): azdata.TextComponent {
|
||||
return this._text;
|
||||
}
|
||||
|
||||
public set text(text: azdata.TextComponent) {
|
||||
this._text = text;
|
||||
}
|
||||
|
||||
public get form(): azdata.FormContainer {
|
||||
return this._form;
|
||||
}
|
||||
|
||||
public set form(form: azdata.FormContainer) {
|
||||
this._form = form;
|
||||
}
|
||||
|
||||
private static convertMetadata(column: ColumnMetadata): any[] {
|
||||
return [column.columnName, column.dataType, false, column.nullable];
|
||||
|
||||
@@ -9,12 +9,60 @@ import * as constants from '../../common/constants';
|
||||
|
||||
export class ProsePreviewPage extends ImportPage {
|
||||
|
||||
private table: azdata.TableComponent;
|
||||
private loading: azdata.LoadingComponent;
|
||||
private form: azdata.FormContainer;
|
||||
private refresh: azdata.ButtonComponent;
|
||||
private resultTextComponent: azdata.TextComponent;
|
||||
private isSuccess: boolean;
|
||||
private _table: azdata.TableComponent;
|
||||
private _loading: azdata.LoadingComponent;
|
||||
private _form: azdata.FormContainer;
|
||||
private _refresh: azdata.ButtonComponent;
|
||||
private _resultTextComponent: azdata.TextComponent;
|
||||
private _isSuccess: boolean;
|
||||
|
||||
public get table(): azdata.TableComponent {
|
||||
return this._table;
|
||||
}
|
||||
|
||||
public set table(table: azdata.TableComponent) {
|
||||
this._table = table;
|
||||
}
|
||||
|
||||
public get loading(): azdata.LoadingComponent {
|
||||
return this._loading;
|
||||
}
|
||||
|
||||
public set loading(loading: azdata.LoadingComponent) {
|
||||
this._loading = loading;
|
||||
}
|
||||
|
||||
public get form(): azdata.FormContainer {
|
||||
return this._form;
|
||||
}
|
||||
|
||||
public set form(form: azdata.FormContainer) {
|
||||
this._form = form;
|
||||
}
|
||||
|
||||
public get refresh(): azdata.ButtonComponent {
|
||||
return this._refresh;
|
||||
}
|
||||
|
||||
public set refresh(refresh: azdata.ButtonComponent) {
|
||||
this._refresh = refresh;
|
||||
}
|
||||
|
||||
public get resultTextComponent(): azdata.TextComponent {
|
||||
return this._resultTextComponent;
|
||||
}
|
||||
|
||||
public set resultTextComponent(resultTextComponent: azdata.TextComponent) {
|
||||
this._resultTextComponent = resultTextComponent;
|
||||
}
|
||||
|
||||
public get isSuccess(): boolean {
|
||||
return this._isSuccess;
|
||||
}
|
||||
|
||||
public set isSuccess(isSuccess: boolean) {
|
||||
this._isSuccess = isSuccess;
|
||||
}
|
||||
|
||||
async start(): Promise<boolean> {
|
||||
this.table = this.view.modelBuilder.table().withProperties<azdata.TableComponentProperties>({
|
||||
|
||||
@@ -10,10 +10,42 @@ import { InsertDataResponse } from '../../services/contracts';
|
||||
import * as constants from '../../common/constants';
|
||||
|
||||
export class SummaryPage extends ImportPage {
|
||||
private table: azdata.TableComponent;
|
||||
private statusText: azdata.TextComponent;
|
||||
private loading: azdata.LoadingComponent;
|
||||
private form: azdata.FormContainer;
|
||||
private _table: azdata.TableComponent;
|
||||
private _statusText: azdata.TextComponent;
|
||||
private _loading: azdata.LoadingComponent;
|
||||
private _form: azdata.FormContainer;
|
||||
|
||||
public get table(): azdata.TableComponent {
|
||||
return this._table;
|
||||
}
|
||||
|
||||
public set table(table: azdata.TableComponent) {
|
||||
this._table = table;
|
||||
}
|
||||
|
||||
public get statusText(): azdata.TextComponent {
|
||||
return this._statusText;
|
||||
}
|
||||
|
||||
public set statusText(statusText: azdata.TextComponent) {
|
||||
this._statusText = statusText;
|
||||
}
|
||||
|
||||
public get loading(): azdata.LoadingComponent {
|
||||
return this._loading;
|
||||
}
|
||||
|
||||
public set loading(loading: azdata.LoadingComponent) {
|
||||
this._loading = loading;
|
||||
}
|
||||
|
||||
public get form(): azdata.FormContainer {
|
||||
return this._form;
|
||||
}
|
||||
|
||||
public set form(form: azdata.FormContainer) {
|
||||
this._form = form;
|
||||
}
|
||||
|
||||
async start(): Promise<boolean> {
|
||||
this.table = this.view.modelBuilder.table().component();
|
||||
@@ -101,7 +133,7 @@ export class SummaryPage extends ImportPage {
|
||||
|
||||
let updateText: string;
|
||||
if (!result || !result.result.success) {
|
||||
updateText = '✗ ';
|
||||
updateText = constants.summaryErrorSymbol;
|
||||
if (!result) {
|
||||
updateText += err;
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user