diff --git a/src/sql/platform/dashboard/browser/interfaces.ts b/src/sql/platform/dashboard/browser/interfaces.ts index f5a577a8aa..55b3a7fd54 100644 --- a/src/sql/platform/dashboard/browser/interfaces.ts +++ b/src/sql/platform/dashboard/browser/interfaces.ts @@ -91,7 +91,12 @@ export interface IComponent extends IDisposable { layout(): void; registerEventHandler(handler: (event: IComponentEventArgs) => void): IDisposable; clearContainer?: () => void; - addToContainer?: (componentDescriptor: IComponentDescriptor, config: any, index?: number) => void; + /** + * Called when child components are added to this component + * @param items The list of items to add. Each item consists of a descriptor for identifying the component, + * the config defined and an optional index to insert it at + */ + addToContainer?: (items: { componentDescriptor: IComponentDescriptor, config: any, index?: number }[]) => void; removeFromContainer?: (componentDescriptor: IComponentDescriptor) => void; setLayout?: (layout: any) => void; setItemLayout?: (componentDescriptor: IComponentDescriptor, config: any) => void; diff --git a/src/sql/platform/model/browser/modelViewService.ts b/src/sql/platform/model/browser/modelViewService.ts index 9a43e79ebc..19f34cc83a 100644 --- a/src/sql/platform/model/browser/modelViewService.ts +++ b/src/sql/platform/model/browser/modelViewService.ts @@ -33,7 +33,12 @@ export interface IModelViewEventArgs extends IComponentEventArgs { export interface IModelView extends IView { initializeModel(rootComponent: IComponentShape, validationCallback?: (componentId: string) => Thenable): void; clearContainer(componentId: string): void; - addToContainer(containerId: string, item: IItemConfig, index?: number): void; + /** + * Adds the specified items as children of the specified parent container + * @param containerId The ID of the container component to add the items to + * @param items The list of items to add to the container + */ + addToContainer(containerId: string, items: { itemConfig: IItemConfig, index?: number }[]): void; removeFromContainer(containerId: string, item: IItemConfig): void; setLayout(componentId: string, layout: any, initial?: boolean): void; setItemLayout(componentId: string, item: IItemConfig): void; diff --git a/src/sql/workbench/api/browser/mainThreadModelView.ts b/src/sql/workbench/api/browser/mainThreadModelView.ts index a407bda894..9c8ebc5fbd 100644 --- a/src/sql/workbench/api/browser/mainThreadModelView.ts +++ b/src/sql/workbench/api/browser/mainThreadModelView.ts @@ -51,9 +51,9 @@ export class MainThreadModelView extends Disposable implements MainThreadModelVi return this.execModelViewAction(handle, (modelView) => modelView.clearContainer(componentId)); } - $addToContainer(handle: number, containerId: string, item: IItemConfig, index?: number): Thenable { + $addToContainer(handle: number, containerId: string, items: { itemConfig: IItemConfig, index?: number }[]): Thenable { return this.execModelViewAction(handle, - (modelView) => modelView.addToContainer(containerId, item, index)); + (modelView) => modelView.addToContainer(containerId, items)); } $removeFromContainer(handle: number, containerId: string, item: IItemConfig): Thenable { diff --git a/src/sql/workbench/api/common/extHostModelView.ts b/src/sql/workbench/api/common/extHostModelView.ts index 5d40ef43b8..e45a290cdb 100644 --- a/src/sql/workbench/api/common/extHostModelView.ts +++ b/src/sql/workbench/api/common/extHostModelView.ts @@ -707,9 +707,12 @@ class ComponentWrapper implements azdata.Component { } public addItems(items: Array, itemLayout?: any): void { - for (let item of items) { - this.addItem(item, itemLayout); - } + const itemConfigs = items.map(item => { + return { + itemConfig: this.createAndAddItemConfig(item, itemLayout).toIItemConfig() + }; + }); + this._proxy.$addToContainer(this._handle, this.id, itemConfigs).then(undefined, (err) => this.handleError(err)); } public removeItemAt(index: number): boolean { @@ -735,11 +738,22 @@ class ComponentWrapper implements azdata.Component { } public addItem(item: azdata.Component, itemLayout?: any, index?: number): void { - let itemImpl = item as ComponentWrapper; + const config = this.createAndAddItemConfig(item, itemLayout, index); + this._proxy.$addToContainer(this._handle, this.id, [{ itemConfig: config.toIItemConfig(), index }]).then(undefined, (err) => this.handleError(err)); + } + + /** + * Creates the internal item config for the component and adds it to the list of child configs for this component. + * @param item The child component to add + * @param itemLayout The optional layout to apply to the child component + * @param index The optional index to insert the child component at + */ + private createAndAddItemConfig(item: azdata.Component, itemLayout?: any, index?: number): InternalItemConfig { + const itemImpl = item as ComponentWrapper; if (!itemImpl) { throw new Error(nls.localize('unknownComponentType', "Unknown component type. Must use ModelBuilder to create objects")); } - let config = new InternalItemConfig(itemImpl, itemLayout); + const config = new InternalItemConfig(itemImpl, itemLayout); if (index !== undefined && index >= 0 && index <= this.items.length) { this.itemConfigs.splice(index, 0, config); } else if (!index) { @@ -747,7 +761,7 @@ class ComponentWrapper implements azdata.Component { } else { throw new Error(nls.localize('invalidIndex', "The index {0} is invalid.", index)); } - this._proxy.$addToContainer(this._handle, this.id, config.toIItemConfig(), index).then(undefined, (err) => this.handleError(err)); + return config; } public setLayout(layout: any): Thenable { @@ -1591,14 +1605,16 @@ class DeclarativeTableWrapper extends ComponentWrapper implements azdata.Declara // data property though since the caller would still expect that to contain // the Component objects they created const properties = assign({}, this.properties); + const componentsToAdd: ComponentWrapper[] = []; if (properties.data?.length > 0) { + properties.data = properties.data.map((row: any[]) => row.map(cell => { if (cell instanceof ComponentWrapper) { // First ensure that we register the component using addItem // such that it gets added to the ModelStore. We don't want to // make the table component an actual container since that exposes // a lot of functionality we don't need. - this.addItem(cell); + componentsToAdd.push(cell); return cell.id; } return cell; @@ -1611,13 +1627,14 @@ class DeclarativeTableWrapper extends ComponentWrapper implements azdata.Declara // such that it gets added to the ModelStore. We don't want to // make the table component an actual container since that exposes // a lot of functionality we don't need. - this.addItem(cell.value); + componentsToAdd.push(cell.value); return { value: cell.value.id, ariaLabel: cell.ariaLabel, style: cell.style }; } return cell; })); } } + this.addItems(componentsToAdd); return properties; } } diff --git a/src/sql/workbench/api/common/sqlExtHost.protocol.ts b/src/sql/workbench/api/common/sqlExtHost.protocol.ts index 115b5fb253..175b956db3 100644 --- a/src/sql/workbench/api/common/sqlExtHost.protocol.ts +++ b/src/sql/workbench/api/common/sqlExtHost.protocol.ts @@ -777,7 +777,7 @@ export interface MainThreadModelViewShape extends IDisposable { $registerProvider(id: string): void; $initializeModel(handle: number, rootComponent: IComponentShape): Thenable; $clearContainer(handle: number, componentId: string): Thenable; - $addToContainer(handle: number, containerId: string, item: IItemConfig, index?: number): Thenable; + $addToContainer(handle: number, containerId: string, items: { itemConfig: IItemConfig, index?: number }[]): Thenable; $removeFromContainer(handle: number, containerId: string, item: IItemConfig): Thenable; $setLayout(handle: number, componentId: string, layout: any): Thenable; $setItemLayout(handle: number, componentId: string, item: IItemConfig): Thenable; diff --git a/src/sql/workbench/browser/modelComponents/componentBase.ts b/src/sql/workbench/browser/modelComponents/componentBase.ts index 967ec02bc1..3a47e8b73f 100644 --- a/src/sql/workbench/browser/modelComponents/componentBase.ts +++ b/src/sql/workbench/browser/modelComponents/componentBase.ts @@ -289,32 +289,34 @@ export abstract class ContainerBase item.descriptor.id === componentDescriptor.id && item.descriptor.type === componentDescriptor.type)) { - return; - } - if (index !== undefined && index !== null && index >= 0 && index <= this.items.length) { - this.items.splice(index, 0, new ItemDescriptor(componentDescriptor, config)); - } else if (!index) { - this.items.push(new ItemDescriptor(componentDescriptor, config)); - } else { - throw new Error(nls.localize('invalidIndex', "The index {0} is invalid.", index)); - } + public addToContainer(items: { componentDescriptor: IComponentDescriptor, config: any, index?: number }[]): void { + items.forEach(newItem => { + this.logService.debug(`Adding component ${newItem.componentDescriptor.id} to container ${this.descriptor.id}`); + if (!newItem.componentDescriptor) { + return; + } + if (this.items.some(item => item.descriptor.id === newItem.componentDescriptor.id && item.descriptor.type === newItem.componentDescriptor.type)) { + return; + } + if (newItem.index !== undefined && newItem.index !== null && newItem.index >= 0 && newItem.index <= this.items.length) { + this.items.splice(newItem.index, 0, new ItemDescriptor(newItem.componentDescriptor, newItem.config)); + } else if (!newItem.index) { + this.items.push(new ItemDescriptor(newItem.componentDescriptor, newItem.config)); + } else { + throw new Error(nls.localize('invalidIndex', "The index {0} is invalid.", newItem.index)); + } - this.logService.debug(`Queueing up action to register validation event handler on component ${componentDescriptor.id} in container ${this.descriptor.id}`); - this.modelStore.eventuallyRunOnComponent(componentDescriptor.id, component => { - this.logService.debug(`Registering validation event handler on component ${componentDescriptor.id} in container ${this.descriptor.id}`); - component.registerEventHandler(async event => { - if (event.eventType === ComponentEventType.validityChanged) { - this.logService.debug(`Running validation on container ${this.descriptor.id} because validity of child component ${componentDescriptor.id} changed`); - this.validate().catch(onUnexpectedError); - } - }); - }, true); + this.logService.debug(`Queueing up action to register validation event handler on component ${newItem.componentDescriptor.id} in container ${this.descriptor.id}`); + this.modelStore.eventuallyRunOnComponent(newItem.componentDescriptor.id, component => { + this.logService.debug(`Registering validation event handler on component ${newItem.componentDescriptor.id} in container ${this.descriptor.id}`); + component.registerEventHandler(async event => { + if (event.eventType === ComponentEventType.validityChanged) { + this.logService.debug(`Running validation on container ${this.descriptor.id} because validity of child component ${newItem.componentDescriptor.id} changed`); + this.validate().catch(onUnexpectedError); + } + }); + }, true); + }); this._changeRef.detectChanges(); this.onItemsUpdated(); return; diff --git a/src/sql/workbench/browser/modelComponents/loadingComponent.component.ts b/src/sql/workbench/browser/modelComponents/loadingComponent.component.ts index 12aefb0257..3d7321a5a0 100644 --- a/src/sql/workbench/browser/modelComponents/loadingComponent.component.ts +++ b/src/sql/workbench/browser/modelComponents/loadingComponent.component.ts @@ -93,8 +93,8 @@ export default class LoadingComponent extends ComponentBase((props) => props.loadingCompletedText, localize('loadingCompletedMessage', "Loading completed")); } - public addToContainer(componentDescriptor: IComponentDescriptor): void { - this._component = componentDescriptor; + public addToContainer(items: { componentDescriptor: IComponentDescriptor }[]): void { + this._component = items[0].componentDescriptor; this.layout(); } diff --git a/src/sql/workbench/browser/modelComponents/viewBase.ts b/src/sql/workbench/browser/modelComponents/viewBase.ts index 6b1c7d89ed..2e3f99f538 100644 --- a/src/sql/workbench/browser/modelComponents/viewBase.ts +++ b/src/sql/workbench/browser/modelComponents/viewBase.ts @@ -68,9 +68,14 @@ export abstract class ViewBase extends AngularDisposable implements IModelView { this.setLayout(component.id, component.layout, true); this.registerEvent(component.id, true); if (component.itemConfigs) { - for (let item of component.itemConfigs) { - this.addToContainer(component.id, item, undefined, true); - } + const items = component.itemConfigs.map(itemConfig => { + return { + itemConfig, + index: undefined, + initial: true + }; + }); + this.addToContainer(component.id, items); } return descriptor; @@ -97,17 +102,26 @@ export abstract class ViewBase extends AngularDisposable implements IModelView { }); } - addToContainer(containerId: string, itemConfig: IItemConfig, index?: number, initial: boolean = false): void { - this.logService.debug(`Queueing action to add component ${itemConfig.componentShape.id} to container ${containerId}`); + addToContainer(containerId: string, items: { itemConfig: IItemConfig, index?: number }[], initial?: boolean): void { + const itemNames = items.map(item => item.itemConfig.componentShape.id).join(','); + this.logService.debug(`Queueing action to add components ${itemNames} to container ${containerId}`); // Do not return the promise as this should be non-blocking this.queueAction(containerId, (component) => { if (!component.addToContainer) { - this.logService.warn(`Container ${containerId} is trying to add component ${itemConfig.componentShape.id} but does not implement addToContainer!`); + this.logService.warn(`Container ${containerId} is trying to add components ${itemNames} but does not implement addToContainer!`); return; } - this.logService.debug(`Adding component ${itemConfig.componentShape.id} to container ${containerId}`); - let childDescriptor = this.defineComponent(itemConfig.componentShape); - component.addToContainer(childDescriptor, itemConfig.config, index); + this.logService.debug(`Adding components ${itemNames} to container ${containerId}`); + const itemConfigs = items.map(item => { + const componentDescriptor = this.defineComponent(item.itemConfig.componentShape); + return { + componentDescriptor, + config: item.itemConfig.config, + index: item.index + }; + }); + + component.addToContainer(itemConfigs); }, initial); } diff --git a/src/sql/workbench/test/electron-browser/api/extHostModelView.test.ts b/src/sql/workbench/test/electron-browser/api/extHostModelView.test.ts index 06c11df9f3..dd08787fc7 100644 --- a/src/sql/workbench/test/electron-browser/api/extHostModelView.test.ts +++ b/src/sql/workbench/test/electron-browser/api/extHostModelView.test.ts @@ -37,7 +37,7 @@ suite('ExtHostModelView Validation Tests', () => { $registerProvider: (id: string) => undefined, $initializeModel: (handle: number, rootComponent: IComponentShape) => undefined, $clearContainer: (handle: number, componentId: string) => undefined, - $addToContainer: (handle: number, containerId: string, item: IItemConfig) => undefined, + $addToContainer: (handle: number, containerId: string, items: { itemConfig: IItemConfig }[]) => undefined, $removeFromContainer: (handle: number, containerId: string, item: IItemConfig) => undefined, $setLayout: (handle: number, componentId: string, layout: any) => undefined, $setProperties: (handle: number, componentId: string, properties: { [key: string]: any }) => undefined, @@ -127,7 +127,7 @@ suite('ExtHostModelView Validation Tests', () => { }); test('Setting a form component as required initializes the model with the component required', () => { - mockProxy.setup(x => x.$addToContainer(It.isAny(), It.isAny(), It.isAny(), undefined)).returns(() => Promise.resolve()); + mockProxy.setup(x => x.$addToContainer(It.isAny(), It.isAny(), It.isAny())).returns(() => Promise.resolve()); // Set up the input component with required initially set to false let inputComponent = modelView.modelBuilder.inputBox().component(); @@ -152,7 +152,7 @@ suite('ExtHostModelView Validation Tests', () => { // Set up the mock proxy to save the component that gets initialized so that it can be verified let rootComponent: IComponentShape; mockProxy.setup(x => x.$initializeModel(It.isAny(), It.isAny())).callback((handle, componentShape) => rootComponent = componentShape); - mockProxy.setup(x => x.$addToContainer(It.isAny(), It.isAny(), It.isAny(), undefined)).returns(() => Promise.resolve()); + mockProxy.setup(x => x.$addToContainer(It.isAny(), It.isAny(), It.isAny())).returns(() => Promise.resolve()); // Set up the form with a top level component and a group let topLevelList = modelView.modelBuilder.listBox().component(); @@ -211,8 +211,7 @@ suite('ExtHostModelView Validation Tests', () => { test('Inserting and removing components from a container should work correctly', () => { mockProxy.setup(x => x.$initializeModel(It.isAny(), It.isAny())); - mockProxy.setup(x => x.$addToContainer(It.isAny(), It.isAny(), It.isAny(), undefined)).returns(() => Promise.resolve()); - mockProxy.setup(x => x.$addToContainer(It.isAny(), It.isAny(), It.isAny(), It.isAny())).returns(() => Promise.resolve()); + mockProxy.setup(x => x.$addToContainer(It.isAny(), It.isAny(), It.isAny())).returns(() => Promise.resolve()); mockProxy.setup(x => x.$removeFromContainer(It.isAny(), It.isAny(), It.isAny())).returns(() => Promise.resolve()); // Set up the form with a top level component and a group let listBox = modelView.modelBuilder.listBox().component(); @@ -234,8 +233,7 @@ suite('ExtHostModelView Validation Tests', () => { test('Inserting component give negative number fails', () => { mockProxy.setup(x => x.$initializeModel(It.isAny(), It.isAny())).callback((handle, componentShape) => { }); - mockProxy.setup(x => x.$addToContainer(It.isAny(), It.isAny(), It.isAny(), undefined)).returns(() => Promise.resolve()); - mockProxy.setup(x => x.$addToContainer(It.isAny(), It.isAny(), It.isAny(), It.isAny())).returns(() => Promise.resolve()); + mockProxy.setup(x => x.$addToContainer(It.isAny(), It.isAny(), It.isAny())).returns(() => Promise.resolve()); mockProxy.setup(x => x.$removeFromContainer(It.isAny(), It.isAny(), It.isAny())).returns(() => Promise.resolve()); // Set up the form with a top level component and a group @@ -253,8 +251,7 @@ suite('ExtHostModelView Validation Tests', () => { test('Inserting component give wrong number fails', () => { mockProxy.setup(x => x.$initializeModel(It.isAny(), It.isAny())).callback((handle, componentShape) => { }); - mockProxy.setup(x => x.$addToContainer(It.isAny(), It.isAny(), It.isAny(), undefined)).returns(() => Promise.resolve()); - mockProxy.setup(x => x.$addToContainer(It.isAny(), It.isAny(), It.isAny(), It.isAny())).returns(() => Promise.resolve()); + mockProxy.setup(x => x.$addToContainer(It.isAny(), It.isAny(), It.isAny())).returns(() => Promise.resolve()); mockProxy.setup(x => x.$removeFromContainer(It.isAny(), It.isAny(), It.isAny())).returns(() => Promise.resolve()); // Set up the form with a top level component and a group @@ -272,8 +269,7 @@ suite('ExtHostModelView Validation Tests', () => { test('Inserting component give end of the list succeeds', () => { mockProxy.setup(x => x.$initializeModel(It.isAny(), It.isAny())).callback((handle, componentShape) => { }); - mockProxy.setup(x => x.$addToContainer(It.isAny(), It.isAny(), It.isAny(), undefined)).returns(() => Promise.resolve()); - mockProxy.setup(x => x.$addToContainer(It.isAny(), It.isAny(), It.isAny(), It.isAny())).returns(() => Promise.resolve()); + mockProxy.setup(x => x.$addToContainer(It.isAny(), It.isAny(), It.isAny())).returns(() => Promise.resolve()); mockProxy.setup(x => x.$removeFromContainer(It.isAny(), It.isAny(), It.isAny())).returns(() => Promise.resolve()); // Set up the form with a top level component and a group @@ -293,8 +289,7 @@ suite('ExtHostModelView Validation Tests', () => { test('Removing a component that does not exist does not fail', () => { // Set up the mock proxy to save the component that gets initialized so that it can be verified mockProxy.setup(x => x.$initializeModel(It.isAny(), It.isAny())); - mockProxy.setup(x => x.$addToContainer(It.isAny(), It.isAny(), It.isAny(), undefined)).returns(() => Promise.resolve()); - mockProxy.setup(x => x.$addToContainer(It.isAny(), It.isAny(), It.isAny(), It.isAny())).returns(() => Promise.resolve()); + mockProxy.setup(x => x.$addToContainer(It.isAny(), It.isAny(), It.isAny())).returns(() => Promise.resolve()); // Set up the form with a top level component and a group let listBox = modelView.modelBuilder.listBox().component(); @@ -314,8 +309,7 @@ suite('ExtHostModelView Validation Tests', () => { test('Inserting and removing component in a form should work correctly', () => { mockProxy.setup(x => x.$initializeModel(It.isAny(), It.isAny())).callback((handle, componentShape) => { }); - mockProxy.setup(x => x.$addToContainer(It.isAny(), It.isAny(), It.isAny(), undefined)).returns(() => Promise.resolve()); - mockProxy.setup(x => x.$addToContainer(It.isAny(), It.isAny(), It.isAny(), It.isAny())).returns(() => Promise.resolve()); + mockProxy.setup(x => x.$addToContainer(It.isAny(), It.isAny(), It.isAny())).returns(() => Promise.resolve()); mockProxy.setup(x => x.$removeFromContainer(It.isAny(), It.isAny(), It.isAny())).returns(() => Promise.resolve()); // Set up the form with a top level component and a group @@ -367,8 +361,7 @@ suite('ExtHostModelView Validation Tests', () => { suite('Declarative table', () => { setup(done => { - mockProxy.setup(x => x.$addToContainer(It.isAny(), It.isAny(), It.isAny(), undefined)).returns(() => Promise.resolve()); - mockProxy.setup(x => x.$addToContainer(It.isAny(), It.isAny(), It.isAny(), It.isAny())).returns(() => Promise.resolve()); + mockProxy.setup(x => x.$addToContainer(It.isAny(), It.isAny(), It.isAny())).returns(() => Promise.resolve()); mockProxy.setup(x => x.$removeFromContainer(It.isAny(), It.isAny(), It.isAny())).returns(() => Promise.resolve()); extHostModelView = new ExtHostModelView(mainContext, undefined, undefined); @@ -439,12 +432,13 @@ suite('ExtHostModelView Validation Tests', () => { rootComponent.properties.data && rootComponent.properties.data[0][0] === button.id; })), Times.once()); - mockProxy.verify(x => x.$addToContainer(It.isAny(), It.isAny(), It.is(item => { + mockProxy.verify(x => x.$addToContainer(It.isAny(), It.isAny(), It.is(items => { + const item = items[0].itemConfig; return item.componentShape.id === declarativeTable.id && item.componentShape.properties && item.componentShape.properties.data && item.componentShape.properties.data[0][0] === button.id; - }), undefined), Times.once()); + })), Times.once()); }); }); }); diff --git a/src/sql/workbench/test/electron-browser/modalComponents/componentBase.test.ts b/src/sql/workbench/test/electron-browser/modalComponents/componentBase.test.ts index cba8261118..861afc8ae0 100644 --- a/src/sql/workbench/test/electron-browser/modalComponents/componentBase.test.ts +++ b/src/sql/workbench/test/electron-browser/modalComponents/componentBase.test.ts @@ -98,7 +98,7 @@ suite('ComponentBase Tests', () => { test('Container validation reflects child component validity', () => { assert.equal(testContainer.valid, true, 'Test container validity did not default to true'); - testContainer.addToContainer(testComponent.descriptor, undefined); + testContainer.addToContainer([{ componentDescriptor: testComponent.descriptor, config: undefined }]); testComponent.addValidation(() => false); return testComponent.validate().then(() => { return testContainer.validate().then(valid => { @@ -121,47 +121,47 @@ suite('ComponentBase Tests', () => { } }); testComponent.addValidation(() => false); - testContainer.addToContainer(testComponent.descriptor, undefined); + testContainer.addToContainer([{ componentDescriptor: testComponent.descriptor, config: undefined }]); testComponent.validate(); }); test('Inserting a component to a container adds the component to the right place', () => { - testContainer.addToContainer(testComponent.descriptor, undefined); + testContainer.addToContainer([{ componentDescriptor: testComponent.descriptor, config: undefined }]); assert.equal(testContainer.TestItems.length, 1, `Unexpected number of items. Expected 1 got ${testContainer.TestItems.length} : ${JSON.stringify(testContainer.TestItems)}`); - testContainer.addToContainer(testComponent2.descriptor, undefined, 0); + testContainer.addToContainer([{ componentDescriptor: testComponent2.descriptor, config: undefined, index: 0 }]); assert.equal(testContainer.TestItems.length, 2, `Unexpected number of items. Expected 2 got ${testContainer.TestItems.length} : ${JSON.stringify(testContainer.TestItems)}`); assert.equal(testContainer.TestItems[0].descriptor.id, testComponent2.descriptor.id); }); test('Inserting a component to a container given negative index fails', () => { - testContainer.addToContainer(testComponent.descriptor, undefined); + testContainer.addToContainer([{ componentDescriptor: testComponent.descriptor, config: undefined }]); assert.equal(testContainer.TestItems.length, 1, `Unexpected number of items. Expected 1 got ${testContainer.TestItems.length} : ${JSON.stringify(testContainer.TestItems)}`); - assert.throws(() => testContainer.addToContainer(testComponent2.descriptor, undefined, -1)); + assert.throws(() => testContainer.addToContainer([{ componentDescriptor: testComponent2.descriptor, config: undefined, index: -1 }])); }); test('Inserting a component to a container given wrong index fails', () => { - testContainer.addToContainer(testComponent.descriptor, undefined); + testContainer.addToContainer([{ componentDescriptor: testComponent.descriptor, config: undefined }]); assert.equal(testContainer.TestItems.length, 1, `Unexpected number of items. Expected 1 got ${testContainer.TestItems.length} : ${JSON.stringify(testContainer.TestItems)}`); - assert.throws(() => testContainer.addToContainer(testComponent2.descriptor, undefined, 10)); + assert.throws(() => testContainer.addToContainer([{ componentDescriptor: testComponent2.descriptor, config: undefined, index: 10 }])); }); test('Inserting a component to a container given end of list succeeds', () => { - testContainer.addToContainer(testComponent.descriptor, undefined); + testContainer.addToContainer([{ componentDescriptor: testComponent.descriptor, config: undefined }]); assert.equal(testContainer.TestItems.length, 1, `Unexpected number of items. Expected 1 got ${testContainer.TestItems.length} : ${JSON.stringify(testContainer.TestItems)}`); - testContainer.addToContainer(testComponent2.descriptor, undefined, 1); + testContainer.addToContainer([{ componentDescriptor: testComponent2.descriptor, config: undefined, index: 1 }]); assert.equal(testContainer.TestItems.length, 2, `Unexpected number of items. Expected 2 got ${testContainer.TestItems.length} : ${JSON.stringify(testContainer.TestItems)}`); }); test('Removing a component the does not exist does not make change in the items', () => { - testContainer.addToContainer(testComponent.descriptor, undefined); + testContainer.addToContainer([{ componentDescriptor: testComponent.descriptor, config: undefined }]); assert.equal(testContainer.TestItems.length, 1, `Unexpected number of items. Expected 1 got ${testContainer.TestItems.length} : ${JSON.stringify(testContainer.TestItems)}`); testContainer.removeFromContainer(testComponent2.descriptor); assert.equal(testContainer.TestItems.length, 1, `Unexpected number of items. Expected 1 got ${testContainer.TestItems.length} : ${JSON.stringify(testContainer.TestItems)}`); }); test('Removing a component removes it from items', () => { - testContainer.addToContainer(testComponent.descriptor, undefined); - testContainer.addToContainer(testComponent2.descriptor, undefined); + testContainer.addToContainer([{ componentDescriptor: testComponent.descriptor, config: undefined }]); + testContainer.addToContainer([{ componentDescriptor: testComponent2.descriptor, config: undefined }]); assert.equal(testContainer.TestItems.length, 2, `Unexpected number of items. Expected 2 got ${testContainer.TestItems.length} : ${JSON.stringify(testContainer.TestItems)}`); testContainer.removeFromContainer(testComponent.descriptor); assert.equal(testContainer.TestItems.length, 1, `Unexpected number of items. Expected 1 got ${testContainer.TestItems.length} : ${JSON.stringify(testContainer.TestItems)}`); @@ -169,9 +169,9 @@ suite('ComponentBase Tests', () => { }); test('Container dost not add same component twice', () => { - testContainer.addToContainer(testComponent.descriptor, undefined); + testContainer.addToContainer([{ componentDescriptor: testComponent.descriptor, config: undefined }]); assert.equal(testContainer.TestItems.length, 1, `Unexpected number of items. Expected 1 got ${testContainer.TestItems.length} : ${JSON.stringify(testContainer.TestItems)}`); - testContainer.addToContainer(testComponent.descriptor, 0); + testContainer.addToContainer([{ componentDescriptor: testComponent.descriptor, config: undefined, index: 0 }]); assert.equal(testContainer.TestItems.length, 1, `Unexpected number of items. Expected 1 got ${testContainer.TestItems.length} : ${JSON.stringify(testContainer.TestItems)}`); }); });