From 4ae6745aac8f68b640b5fc724575618ebb9ef144 Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Tue, 3 Dec 2019 16:09:46 +0100 Subject: [PATCH] chore(util-registry): refactor + new unit tests for start --- frontend/src/app.js | 2 +- frontend/src/app.spec.js | 4 +- .../services/util-registry/util-registry.js | 20 +++++-- .../util-registry/util-registry.spec.js | 58 +++++++++++++++++-- frontend/src/utils/async-table/async-table.js | 2 +- .../src/utils/async-table/async-table.spec.js | 2 +- frontend/src/utils/check-all/check-all.js | 2 +- .../src/utils/check-all/check-all.spec.js | 2 +- frontend/src/utils/mass-input/mass-input.js | 2 +- frontend/src/utils/modal/modal.js | 2 +- 10 files changed, 79 insertions(+), 17 deletions(-) diff --git a/frontend/src/app.js b/frontend/src/app.js index 8b26b08a2..66a9760b9 100644 --- a/frontend/src/app.js +++ b/frontend/src/app.js @@ -15,7 +15,7 @@ export class App { constructor() { this.utilRegistry.setApp(this); - document.addEventListener('DOMContentLoaded', () => this.utilRegistry.setupAll()); + document.addEventListener('DOMContentLoaded', () => this.utilRegistry.initAll()); } registerUtilities(utils) { diff --git a/frontend/src/app.spec.js b/frontend/src/app.spec.js index e682f0e28..f1f5df476 100644 --- a/frontend/src/app.spec.js +++ b/frontend/src/app.spec.js @@ -24,9 +24,9 @@ describe('App', () => { }); it('should setup all utlites when page is done loading', () => { - spyOn(global.App.utilRegistry, 'setupAll'); + spyOn(global.App.utilRegistry, 'initAll'); document.dispatchEvent(new Event('DOMContentLoaded')); - expect(global.App.utilRegistry.setupAll).toHaveBeenCalled(); + expect(global.App.utilRegistry.initAll).toHaveBeenCalled(); }); describe('provides services', () => { diff --git a/frontend/src/services/util-registry/util-registry.js b/frontend/src/services/util-registry/util-registry.js index bd4f49c9f..f5c409351 100644 --- a/frontend/src/services/util-registry/util-registry.js +++ b/frontend/src/services/util-registry/util-registry.js @@ -13,6 +13,9 @@ export class UtilRegistry { * name: string | utils name, e.g. 'example' * selector: string | utils selector, e.g. '[uw-example]' * setup: Function | utils setup function, see below + * + * optional util properties: + * start: Function | utils start function, see below * * setup function must return instance object with at least these properties: * name: string | utils name @@ -47,14 +50,19 @@ export class UtilRegistry { this._appInstance = appInstance; } - setupAll(scope) { + initAll(scope) { const setupInstances = this._registeredUtils.map((util) => this.setup(util, scope)).flat(); - setupInstances.forEach((instance) => typeof instance.start === 'function' && instance.start()); + + setupInstances + .filter((instance) => instance && typeof instance.start === 'function') + .forEach((instance) => this.start(instance)); if (DEBUG_MODE > 1) { - console.info('setup js instances:'); + console.info('initialized js util instances:'); console.table(setupInstances); } + + return setupInstances; } setup(util, scope = document.body) { @@ -74,7 +82,7 @@ export class UtilRegistry { utilInstance = new util(element, this._appInstance); } catch(err) { if (DEBUG_MODE > 0) { - console.warn('Error while trying to initialize a utility!', { util , element, err }); + console.error('Error while trying to initialize a utility!', { util , element, err }); } } @@ -92,6 +100,10 @@ export class UtilRegistry { return instances.map(instance => ({ scope: scope, util: util, ...instance })); } + start(instance) { + instance.start(); + } + find(name) { return this._registeredUtils.find((util) => util.name === name); } diff --git a/frontend/src/services/util-registry/util-registry.spec.js b/frontend/src/services/util-registry/util-registry.spec.js index 5f29f6a3c..087ec0817 100644 --- a/frontend/src/services/util-registry/util-registry.spec.js +++ b/frontend/src/services/util-registry/util-registry.spec.js @@ -103,26 +103,70 @@ describe('UtilRegistry', () => { }); }); - describe('setupAll()', () => { + describe('initAll()', () => { it('should setup all the utilities', () => { spyOn(utilRegistry, 'setup'); utilRegistry.register(TestUtil1); utilRegistry.register(TestUtil2); - utilRegistry.setupAll(); + utilRegistry.register(TestUtil3); + utilRegistry.initAll(); - expect(utilRegistry.setup.calls.count()).toBe(2); + expect(utilRegistry.setup.calls.count()).toBe(3); expect(utilRegistry.setup.calls.argsFor(0)).toEqual([TestUtil1, undefined]); expect(utilRegistry.setup.calls.argsFor(1)).toEqual([TestUtil2, undefined]); + expect(utilRegistry.setup.calls.argsFor(2)).toEqual([TestUtil3, undefined]); }); it('should pass the given scope', () => { spyOn(utilRegistry, 'setup'); utilRegistry.register(TestUtil1); const scope = document.createElement('div'); - utilRegistry.setupAll(scope); + utilRegistry.initAll(scope); expect(utilRegistry.setup).toHaveBeenCalledWith(TestUtil1, scope); }); + + describe('starts startable util instances', () => { + let testScope, + testElement1, + testElement2, + testElement3, + testElement4; + + beforeEach(() => { + testScope = document.createElement('div'); + + testElement1 = document.createElement('div'); + testElement2 = document.createElement('div'); + testElement3 = document.createElement('div'); + testElement4 = document.createElement('div'); + + testElement1.classList.add('util1'); + testElement2.id = 'util2'; + testElement3.classList.add('util3'); + testElement4.classList.add('util3'); + + testScope.appendChild(testElement1); + testScope.appendChild(testElement2); + testScope.appendChild(testElement3); + testScope.appendChild(testElement4); + }); + + it('should start instances that provide a start function', () => { + spyOn(utilRegistry, 'start'); + utilRegistry.register(TestUtil3); + utilRegistry.initAll(testScope); + expect(utilRegistry.start.calls.count()).toBe(2); + }); + + it('should not start instances that do not provide a start function', () => { + spyOn(utilRegistry, 'start'); + utilRegistry.register(TestUtil1); + utilRegistry.register(TestUtil2); + utilRegistry.initAll(testScope); + expect(utilRegistry.start).not.toHaveBeenCalled(); + }); + }); }); }); @@ -138,6 +182,12 @@ class TestUtil1 { @Utility({ selector: '#util2' }) class TestUtil2 { } +@Utility({ selector: '.util3' }) +class TestUtil3 { + constructor() {} + start() {} +} + @Utility({ selector: '#throws' }) class ThrowingUtil { constructor() { diff --git a/frontend/src/utils/async-table/async-table.js b/frontend/src/utils/async-table/async-table.js index 7ac679c5f..69e67250b 100644 --- a/frontend/src/utils/async-table/async-table.js +++ b/frontend/src/utils/async-table/async-table.js @@ -364,7 +364,7 @@ export class AsyncTable { // update table with new this._element.innerHTML = response.element.innerHTML; - this._app.utilRegistry.setupAll(this._element); + this._app.utilRegistry.initAll(this._element); if (callback && typeof callback === 'function') { this._storageManager.save('cssIdPrefix', response.idPrefix); diff --git a/frontend/src/utils/async-table/async-table.spec.js b/frontend/src/utils/async-table/async-table.spec.js index 7dc36be0c..d72b4c1ec 100644 --- a/frontend/src/utils/async-table/async-table.spec.js +++ b/frontend/src/utils/async-table/async-table.spec.js @@ -8,7 +8,7 @@ const AppTestMock = { parseResponse: () => {}, }, utilRegistry: { - setupAll: () => {}, + initAll: () => {}, }, }; diff --git a/frontend/src/utils/check-all/check-all.js b/frontend/src/utils/check-all/check-all.js index 340dca0b1..d196aae51 100644 --- a/frontend/src/utils/check-all/check-all.js +++ b/frontend/src/utils/check-all/check-all.js @@ -93,7 +93,7 @@ export class CheckAll { th.insertBefore(this._checkAllCheckbox, th.firstChild); // set up new checkbox - this._app.utilRegistry.setupAll(th); + this._app.utilRegistry.initAll(th); this._checkAllCheckbox.addEventListener('input', () => this._onCheckAllCheckboxInput()); this._setupCheckboxListeners(); diff --git a/frontend/src/utils/check-all/check-all.spec.js b/frontend/src/utils/check-all/check-all.spec.js index a04e50c41..b9697fe3c 100644 --- a/frontend/src/utils/check-all/check-all.spec.js +++ b/frontend/src/utils/check-all/check-all.spec.js @@ -2,7 +2,7 @@ import { CheckAll } from './check-all'; const MOCK_APP = { utilRegistry: { - setupAll: () => {}, + initAll: () => {}, }, }; diff --git a/frontend/src/utils/mass-input/mass-input.js b/frontend/src/utils/mass-input/mass-input.js index 403c626ac..dee124a1a 100644 --- a/frontend/src/utils/mass-input/mass-input.js +++ b/frontend/src/utils/mass-input/mass-input.js @@ -155,7 +155,7 @@ export class MassInput { this._reset(); - this._app.utilRegistry.setupAll(this._element); + this._app.utilRegistry.initAll(this._element); } _serializeForm(submitButton, enctype) { diff --git a/frontend/src/utils/modal/modal.js b/frontend/src/utils/modal/modal.js index 52a9a2b99..c67b13ac7 100644 --- a/frontend/src/utils/modal/modal.js +++ b/frontend/src/utils/modal/modal.js @@ -177,6 +177,6 @@ export class Modal { this._element.insertBefore(modalContent, null); // setup any newly arrived utils - this._app.utilRegistry.setupAll(this._element); + this._app.utilRegistry.initAll(this._element); } }