diff --git a/lib/src/commands/LayoutTreeCrawler.test.ts b/lib/src/commands/LayoutTreeCrawler.test.ts index 998fccc01e1..1523366da60 100644 --- a/lib/src/commands/LayoutTreeCrawler.test.ts +++ b/lib/src/commands/LayoutTreeCrawler.test.ts @@ -104,6 +104,136 @@ describe('LayoutTreeCrawler', () => { }); }); + it('Components: extract button style from passedOptions buttons array and merge it to all buttons', () => { + const MyComponent = class { + static get options() { + return { + topBar: { + leftButtons: [{ + id: 'id' + }, { + id: 'id2' + }], + rightButtons: [{ + id: 'id3' + }] + } + }; + } + }; + + const passedOptions = { + topBar: { + leftButtons: { + font: 'Helvetica' + }, + rightButtons: [] + } + }; + + const node = { type: LayoutType.Component, data: { name: 'theComponentName', options: passedOptions } }; + store.setOriginalComponentClassForName('theComponentName', MyComponent); + + uut.crawl(node); + + expect(node.data.options).toEqual({ + topBar: { + leftButtons: [{ + id: 'id', + font: 'Helvetica' + }, { + id: 'id2', + font: 'Helvetica' + }], + rightButtons: [{ + id: 'id3' + }] + } + }); + }); + + it('Components: empty buttons array should not affect static buttons', () => { + const MyComponent = class { + static get options() { + return { + topBar: {} + }; + } + }; + + const passedOptions = { + topBar: {} + }; + + const node = { type: LayoutType.Component, data: { name: 'theComponentName', options: passedOptions } }; + store.setOriginalComponentClassForName('theComponentName', MyComponent); + + uut.crawl(node); + + expect(node.data.options).toEqual({ + topBar: {} + }); + }); + + it('Components: static options with no topBar should not crash', () => { + const MyComponent = class { + static get options() { + return { + + }; + } + }; + + const passedOptions = { + topBar: {} + }; + + const node = { type: LayoutType.Component, data: { name: 'theComponentName', options: passedOptions } }; + store.setOriginalComponentClassForName('theComponentName', MyComponent); + + uut.crawl(node); + + expect(node.data.options).toEqual({ + topBar: {} + }); + }); + + it('Components: undefined passed buttons should not affect static buttons', () => { + const MyComponent = class { + static get options() { + return { + topBar: { + leftButtons: [{ + id: 'id' + }], + rightButtons: [{ + id: 'id2' + }] + } + }; + } + }; + + const passedOptions = { + topBar: {} + }; + + const node = { type: LayoutType.Component, data: { name: 'theComponentName', options: passedOptions } }; + store.setOriginalComponentClassForName('theComponentName', MyComponent); + + uut.crawl(node); + + expect(node.data.options).toEqual({ + topBar: { + leftButtons: [{ + id: 'id' + }], + rightButtons: [{ + id: 'id2' + }] + } + }); + }); it('Component: deepClones options', () => { const theStyle = {}; const MyComponent = class { diff --git a/lib/src/commands/LayoutTreeCrawler.ts b/lib/src/commands/LayoutTreeCrawler.ts index 3dfe4acd1f4..0d00c89d85c 100644 --- a/lib/src/commands/LayoutTreeCrawler.ts +++ b/lib/src/commands/LayoutTreeCrawler.ts @@ -54,9 +54,46 @@ export class LayoutTreeCrawler { const clazz = this.store.getOriginalComponentClassForName(node.data.name) || {}; const staticOptions = _.cloneDeep(clazz.options) || {}; const passedOptions = node.data.options || {}; + this._mergeButtonsStyles(passedOptions, staticOptions); node.data.options = _.merge({}, staticOptions, passedOptions); } + _mergeButtonsStyles(passedOptions, staticOptions) { + if (passedOptions.topBar) { + this._normalizeButtons(passedOptions.topBar.leftButtons, (buttons, style) => { + passedOptions.topBar.leftButtons = buttons; + + if (staticOptions.topBar) { + this._applyButtonsStyle(staticOptions.topBar.leftButtons, style); + } + }); + + this._normalizeButtons(passedOptions.topBar.rightButtons, (buttons, style) => { + passedOptions.topBar.rightButtons = buttons; + + if (staticOptions.topBar) { + this._applyButtonsStyle(staticOptions.topBar.rightButtons, style); + } + }); + } + } + + _normalizeButtons(buttons, callback) { + if (_.isPlainObject(buttons)) { + callback([], buttons); + } else { + callback(buttons); + } + } + + _applyButtonsStyle(buttons, style) { + if (buttons) { + buttons.forEach((button) => { + _.merge(button, style); + }); + } + } + _assertKnownLayoutType(type) { if (!LayoutType[type]) { throw new Error(`Unknown layout type ${type}`);