diff --git a/extensions/import/src/test/wizard/pages/fileConfigPage.test.ts b/extensions/import/src/test/wizard/pages/fileConfigPage.test.ts index 8f4fb35a12..153896d4e0 100644 --- a/extensions/import/src/test/wizard/pages/fileConfigPage.test.ts +++ b/extensions/import/src/test/wizard/pages/fileConfigPage.test.ts @@ -86,7 +86,7 @@ describe('File config page', function () { it('checking if all components are initialized properly', async function () { - await new Promise(function (resolve) { + await new Promise(function (resolve) { page.registerContent(async (view) => { fileConfigPage = new FileConfigPage(mockFlatFileWizard.object, page, mockImportModel.object, view, TypeMoq.It.isAny()); pages.set(1, fileConfigPage); @@ -143,7 +143,6 @@ describe('File config page', function () { providerName: 'PGSQL', connectionId: 'testConnection3Id', options: { - user: undefined, // setting it undefined to check if function return user as 'default server: 'testcon3server', database: 'testdb3' } @@ -156,7 +155,7 @@ describe('File config page', function () { providerName: 'MSSQL', connectionId: 'testConnection2Id', options: { - // default database. This datatabe will be the first value in the database dropdown + // default database. This database will be the first value in the database dropdown database: 'testdb2', user: 'testcon2user', server: 'testcon2server' @@ -230,16 +229,16 @@ describe('File config page', function () { { displayName: 'schema3', name: 'schema3' } ]; - let mockQueryProvider = TypeMoq.Mock.ofType(TestQueryProvider); - sinon.stub(azdata.dataprotocol, 'getProvider').returns(mockQueryProvider.object); - mockQueryProvider.setup(x => x.runQueryAndReturn(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(async () => { return schemaQueryResult; }); + const testQueryProvider = new TestQueryProvider(); + sinon.stub(azdata.dataprotocol, 'getProvider').returns(testQueryProvider); + sinon.stub(testQueryProvider, 'runQueryAndReturn').resolves(schemaQueryResult); - await new Promise(function (resolve) { + await new Promise(function (resolve) { page.registerContent(async (view) => { fileConfigPage = new FileConfigPage(mockFlatFileWizard.object, page, mockImportModel.object, view, TypeMoq.It.isAny()); pages.set(1, fileConfigPage); await fileConfigPage.start(); - await fileConfigPage.setupNavigationValidator(); + fileConfigPage.setupNavigationValidator(); resolve(); }); wizard.generateScriptButton.hidden = true; @@ -251,11 +250,11 @@ describe('File config page', function () { 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); + should.deepEqual(fileConfigPage.serverDropdown.value, expectedConnectionValues[0], 'Server dropdown value was incorrect'); + should.deepEqual(fileConfigPage.serverDropdown.values, expectedConnectionValues, 'Server dropdown values were incorrect'); + should.deepEqual(fileConfigPage.databaseDropdown.value, expectedDatabaseDropdownValues[0], 'Database dropdown value was incorrect'); + should.deepEqual(fileConfigPage.databaseDropdown.values, expectedDatabaseDropdownValues, 'Database dropdown values were incorrect'); + should.deepEqual(fileConfigPage.schemaDropdown.value, expectedSchemaValues[0], 'Schema dropdown value was incorrect'); + should.deepEqual(fileConfigPage.schemaDropdown.values, expectedSchemaValues, 'Schema dropdown values were incorrect'); }); }); diff --git a/extensions/import/src/test/wizard/pages/modifyColumnsPage.test.ts b/extensions/import/src/test/wizard/pages/modifyColumnsPage.test.ts index 707691f1e8..e7cf3471a5 100644 --- a/extensions/import/src/test/wizard/pages/modifyColumnsPage.test.ts +++ b/extensions/import/src/test/wizard/pages/modifyColumnsPage.test.ts @@ -36,7 +36,7 @@ describe('import extension modify Column Page', function () { it('checking if all components are initialized properly', async function () { - await new Promise(function (resolve) { + await new Promise(function (resolve) { page.registerContent(async (view) => { modifyColumnsPage = new ModifyColumnsPage(mockFlatFileWizard.object, page, mockImportModel.object, view, TypeMoq.It.isAny()); pages.set(1, modifyColumnsPage); @@ -81,7 +81,7 @@ describe('import extension modify Column Page', function () { mockImportModel.object.proseColumns = testProseColumns; - await new Promise(function (resolve) { + await new Promise(function (resolve) { page.registerContent(async (view) => { modifyColumnsPage = new ModifyColumnsPage(mockFlatFileWizard.object, page, mockImportModel.object, view, TypeMoq.It.isAny()); pages.set(1, modifyColumnsPage); diff --git a/extensions/import/src/test/wizard/pages/prosePreviewPage.test.ts b/extensions/import/src/test/wizard/pages/prosePreviewPage.test.ts index dde3e99289..7f451ceb81 100644 --- a/extensions/import/src/test/wizard/pages/prosePreviewPage.test.ts +++ b/extensions/import/src/test/wizard/pages/prosePreviewPage.test.ts @@ -41,12 +41,12 @@ describe('import extension prose preview tests', function () { it('checking if all components are initialized properly', async function () { // Opening the wizard and initializing the page as ProsePreviewPage - await new Promise(function (resolve) { + await new Promise(function (resolve) { page.registerContent(async (view) => { prosePreviewPage = new ProsePreviewPage(mockFlatFileWizard.object, page, mockImportModel.object, view, TypeMoq.It.isAny()); pages.set(1, prosePreviewPage); await prosePreviewPage.start(); - await prosePreviewPage.setupNavigationValidator(); + prosePreviewPage.setupNavigationValidator(); await prosePreviewPage.onPageEnter(); resolve(); }); diff --git a/extensions/import/src/test/wizard/pages/summaryPage.test.ts b/extensions/import/src/test/wizard/pages/summaryPage.test.ts index 28870f27c5..e869d2cb57 100644 --- a/extensions/import/src/test/wizard/pages/summaryPage.test.ts +++ b/extensions/import/src/test/wizard/pages/summaryPage.test.ts @@ -38,7 +38,7 @@ describe('import extension summary page tests', function () { it('checking if all components are initialized properly', async function () { - await new Promise(function (resolve) { + await new Promise(function (resolve) { page.registerContent(async (view) => { summaryPage = new SummaryPage(mockFlatFileWizard.object, page, mockImportModel.object, view, TypeMoq.It.isAny()); pages.set(1, summaryPage); @@ -105,7 +105,7 @@ describe('import extension summary page tests', function () { }; mockFlatFileProvider.setup(x => x.sendInsertDataRequest(TypeMoq.It.isAny())).returns(async () => { return testSendInsertDataRequestResponse; }); - await new Promise(function (resolve) { + await new Promise(function (resolve) { page.registerContent(async (view) => { summaryPage = new SummaryPage(mockFlatFileWizard.object, page, mockImportModel.object, view, mockFlatFileProvider.object); pages.set(1, summaryPage); diff --git a/extensions/import/src/wizard/pages/fileConfigPage.ts b/extensions/import/src/wizard/pages/fileConfigPage.ts index bb340f30c6..c59becb794 100644 --- a/extensions/import/src/wizard/pages/fileConfigPage.ts +++ b/extensions/import/src/wizard/pages/fileConfigPage.ts @@ -144,8 +144,12 @@ export class FileConfigPage extends ImportPage { }).component(); // Handle server changes - this.serverDropdown.onValueChanged(async (params) => { - this.model.server = (this.serverDropdown.value as ConnectionDropdownValue).connection; + this.serverDropdown.onValueChanged(async () => { + const connectionValue = this.serverDropdown.value as ConnectionDropdownValue; + if (!connectionValue) { + return; + } + this.model.server = connectionValue.connection; await this.populateDatabaseDropdown(); await this.populateSchemaDropdown(); @@ -165,10 +169,7 @@ export class FileConfigPage extends ImportPage { this.model.server = values[0].connection; - - this.serverDropdown.updateProperties({ - values: values - }); + this.serverDropdown.values = values; return true; } @@ -178,9 +179,15 @@ export class FileConfigPage extends ImportPage { }).component(); // Handle database changes - this.databaseDropdown.onValueChanged(async (db) => { - this.model.database = (this.databaseDropdown.value).name; - //this.populateTableNames(); + this.databaseDropdown.onValueChanged(async () => { + const nameValue = this.databaseDropdown.value as azdata.CategoryValue; + if (!nameValue) { + return; + } + this.model.database = nameValue.name; + if (!this.model.server) { + return; + } let connectionProvider = azdata.dataprotocol.getProvider(this.model.server.providerName, azdata.DataProviderType.ConnectionProvider); let connectionUri = await azdata.connection.getUriForConnection(this.model.server.connectionId); connectionProvider.changeDatabase(connectionUri, this.model.database); @@ -195,8 +202,8 @@ export class FileConfigPage extends ImportPage { private async populateDatabaseDropdown(): Promise { this.databaseDropdown.loading = true; - this.databaseDropdown.updateProperties({ values: [] }); - this.schemaDropdown.updateProperties({ values: [] }); + this.databaseDropdown.values = []; + this.schemaDropdown.values = []; if (!this.model.server) { //TODO handle error case @@ -340,7 +347,11 @@ export class FileConfigPage extends ImportPage { this.schemaLoader = this.view.modelBuilder.loadingComponent().withItem(this.schemaDropdown).component(); this.schemaDropdown.onValueChanged(() => { - this.model.schema = (this.schemaDropdown.value).name; + const schemaValue = this.schemaDropdown.value as azdata.CategoryValue; + if (!schemaValue) { + return; + } + this.model.schema = schemaValue.name; }); @@ -356,22 +367,22 @@ export class FileConfigPage extends ImportPage { let values = await this.getSchemaValues(); - this.model.schema = values[0].name; + this.model.schema = values[0]?.name; - this.schemaDropdown.updateProperties({ - values: values - }); + this.schemaDropdown.values = values; this.schemaLoader.loading = false; return true; } public async getSchemaValues(): Promise<{ displayName: string, name: string }[]> { + if (!this.model.server) { + return []; + } let connectionUri = await azdata.connection.getUriForConnection(this.model.server.connectionId); let queryProvider = azdata.dataprotocol.getProvider(this.model.server.providerName, azdata.DataProviderType.QueryProvider); let results = await queryProvider.runQueryAndReturn(connectionUri, constants.selectSchemaQuery); - let idx = -1; let count = -1; diff --git a/src/sql/base/browser/ui/selectBox/selectBox.ts b/src/sql/base/browser/ui/selectBox/selectBox.ts index fa2f3d15b8..7e1350124d 100644 --- a/src/sql/base/browser/ui/selectBox/selectBox.ts +++ b/src/sql/base/browser/ui/selectBox/selectBox.ts @@ -16,6 +16,7 @@ import { renderFormattedText, renderText, FormattedTextRenderOptions } from 'vs/ import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; import { SelectBoxList } from 'vs/base/browser/ui/selectBox/selectBoxCustom'; +import { Event, Emitter } from 'vs/base/common/event'; const $ = dom.$; @@ -51,6 +52,7 @@ export class SelectBox extends vsSelectBox { private disabledSelectBorder?: Color; private contextViewProvider: IContextViewProvider; private message?: IMessage; + private _onDidSelect: Emitter; private inputValidationInfoBorder?: Color; private inputValidationInfoBackground?: Color; @@ -68,6 +70,7 @@ export class SelectBox extends vsSelectBox { let optionItems: SelectOptionItemSQL[] = SelectBox.createOptions(options); super(optionItems, 0, contextViewProvider, undefined, selectBoxOptions); + this._onDidSelect = new Emitter(); this._optionsDictionary = new Map(); this.populateOptionsDictionary(optionItems); this._dialogOptions = optionItems; @@ -77,7 +80,8 @@ export class SelectBox extends vsSelectBox { } this._selectedOption = selectedOption; - this._register(this.onDidSelect(newSelect => { + this._register(super.onDidSelect(newSelect => { + this._onDidSelect.fire(newSelect); this.onSelect(newSelect); })); @@ -121,6 +125,14 @@ export class SelectBox extends vsSelectBox { } } + public get onDidSelect(): Event { + // We override the onDidSelect event here because the base onDidSelect event isn't fired when + // selecting an element via select - which means that we'll miss out on a selection made that way. + // So we expose our own event that's fired either when the base onDidSelect is called or when we + // manually select an item + return this._onDidSelect.event; + } + public onSelect(newInput: ISelectData) { const selected = this._dialogOptions[newInput.index]; this._selectedOption = selected.value; @@ -189,6 +201,10 @@ export class SelectBox extends vsSelectBox { if (this._dialogOptions !== undefined) { this._selectedOption = this._dialogOptions[index]?.value; } + this._onDidSelect.fire({ + selected: this._selectedOption, + index: index + }); }