chore(util-registry): refactor + new unit tests for start

This commit is contained in:
Sarah Vaupel 2019-12-03 16:09:46 +01:00 committed by Gregor Kleen
parent 00584f9590
commit 4ae6745aac
10 changed files with 79 additions and 17 deletions

View File

@ -15,7 +15,7 @@ export class App {
constructor() { constructor() {
this.utilRegistry.setApp(this); this.utilRegistry.setApp(this);
document.addEventListener('DOMContentLoaded', () => this.utilRegistry.setupAll()); document.addEventListener('DOMContentLoaded', () => this.utilRegistry.initAll());
} }
registerUtilities(utils) { registerUtilities(utils) {

View File

@ -24,9 +24,9 @@ describe('App', () => {
}); });
it('should setup all utlites when page is done loading', () => { 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')); document.dispatchEvent(new Event('DOMContentLoaded'));
expect(global.App.utilRegistry.setupAll).toHaveBeenCalled(); expect(global.App.utilRegistry.initAll).toHaveBeenCalled();
}); });
describe('provides services', () => { describe('provides services', () => {

View File

@ -13,6 +13,9 @@ export class UtilRegistry {
* name: string | utils name, e.g. 'example' * name: string | utils name, e.g. 'example'
* selector: string | utils selector, e.g. '[uw-example]' * selector: string | utils selector, e.g. '[uw-example]'
* setup: Function | utils setup function, see below * 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: * setup function must return instance object with at least these properties:
* name: string | utils name * name: string | utils name
@ -47,14 +50,19 @@ export class UtilRegistry {
this._appInstance = appInstance; this._appInstance = appInstance;
} }
setupAll(scope) { initAll(scope) {
const setupInstances = this._registeredUtils.map((util) => this.setup(util, scope)).flat(); 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) { if (DEBUG_MODE > 1) {
console.info('setup js instances:'); console.info('initialized js util instances:');
console.table(setupInstances); console.table(setupInstances);
} }
return setupInstances;
} }
setup(util, scope = document.body) { setup(util, scope = document.body) {
@ -74,7 +82,7 @@ export class UtilRegistry {
utilInstance = new util(element, this._appInstance); utilInstance = new util(element, this._appInstance);
} catch(err) { } catch(err) {
if (DEBUG_MODE > 0) { 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 })); return instances.map(instance => ({ scope: scope, util: util, ...instance }));
} }
start(instance) {
instance.start();
}
find(name) { find(name) {
return this._registeredUtils.find((util) => util.name === name); return this._registeredUtils.find((util) => util.name === name);
} }

View File

@ -103,26 +103,70 @@ describe('UtilRegistry', () => {
}); });
}); });
describe('setupAll()', () => { describe('initAll()', () => {
it('should setup all the utilities', () => { it('should setup all the utilities', () => {
spyOn(utilRegistry, 'setup'); spyOn(utilRegistry, 'setup');
utilRegistry.register(TestUtil1); utilRegistry.register(TestUtil1);
utilRegistry.register(TestUtil2); 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(0)).toEqual([TestUtil1, undefined]);
expect(utilRegistry.setup.calls.argsFor(1)).toEqual([TestUtil2, 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', () => { it('should pass the given scope', () => {
spyOn(utilRegistry, 'setup'); spyOn(utilRegistry, 'setup');
utilRegistry.register(TestUtil1); utilRegistry.register(TestUtil1);
const scope = document.createElement('div'); const scope = document.createElement('div');
utilRegistry.setupAll(scope); utilRegistry.initAll(scope);
expect(utilRegistry.setup).toHaveBeenCalledWith(TestUtil1, 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' }) @Utility({ selector: '#util2' })
class TestUtil2 { } class TestUtil2 { }
@Utility({ selector: '.util3' })
class TestUtil3 {
constructor() {}
start() {}
}
@Utility({ selector: '#throws' }) @Utility({ selector: '#throws' })
class ThrowingUtil { class ThrowingUtil {
constructor() { constructor() {

View File

@ -364,7 +364,7 @@ export class AsyncTable {
// update table with new // update table with new
this._element.innerHTML = response.element.innerHTML; this._element.innerHTML = response.element.innerHTML;
this._app.utilRegistry.setupAll(this._element); this._app.utilRegistry.initAll(this._element);
if (callback && typeof callback === 'function') { if (callback && typeof callback === 'function') {
this._storageManager.save('cssIdPrefix', response.idPrefix); this._storageManager.save('cssIdPrefix', response.idPrefix);

View File

@ -8,7 +8,7 @@ const AppTestMock = {
parseResponse: () => {}, parseResponse: () => {},
}, },
utilRegistry: { utilRegistry: {
setupAll: () => {}, initAll: () => {},
}, },
}; };

View File

@ -93,7 +93,7 @@ export class CheckAll {
th.insertBefore(this._checkAllCheckbox, th.firstChild); th.insertBefore(this._checkAllCheckbox, th.firstChild);
// set up new checkbox // set up new checkbox
this._app.utilRegistry.setupAll(th); this._app.utilRegistry.initAll(th);
this._checkAllCheckbox.addEventListener('input', () => this._onCheckAllCheckboxInput()); this._checkAllCheckbox.addEventListener('input', () => this._onCheckAllCheckboxInput());
this._setupCheckboxListeners(); this._setupCheckboxListeners();

View File

@ -2,7 +2,7 @@ import { CheckAll } from './check-all';
const MOCK_APP = { const MOCK_APP = {
utilRegistry: { utilRegistry: {
setupAll: () => {}, initAll: () => {},
}, },
}; };

View File

@ -155,7 +155,7 @@ export class MassInput {
this._reset(); this._reset();
this._app.utilRegistry.setupAll(this._element); this._app.utilRegistry.initAll(this._element);
} }
_serializeForm(submitButton, enctype) { _serializeForm(submitButton, enctype) {

View File

@ -177,6 +177,6 @@ export class Modal {
this._element.insertBefore(modalContent, null); this._element.insertBefore(modalContent, null);
// setup any newly arrived utils // setup any newly arrived utils
this._app.utilRegistry.setupAll(this._element); this._app.utilRegistry.initAll(this._element);
} }
} }