import { UtilRegistry } from './util-registry'; import { Utility } from '../../core/utility'; describe('UtilRegistry', () => { let utilRegistry; beforeEach(() => { utilRegistry = new UtilRegistry(); }); it('should create', () => { expect(utilRegistry).toBeTruthy(); }); describe('register()', () => { it('should allow to add utilities', () => { let foundUtil = utilRegistry.find(TestUtil1.name); expect(foundUtil).toBeFalsy(); utilRegistry.register(TestUtil1); foundUtil = utilRegistry.find(TestUtil1.name); expect(foundUtil).toEqual(TestUtil1); }); }); describe('setup()', () => { it('should catch errors thrown by the utility', () => { expect(() => { utilRegistry.setup(ThrowingUtil); }).not.toThrow(); }); describe('scope has no matching elements', () => { it('should not construct an instance', () => { const scope = document.createElement('div'); const instances = utilRegistry.setup(TestUtil1, scope); expect(instances.length).toBe(0); }); it('should use fallback scope', () => { const instances = utilRegistry.setup(TestUtil1); expect(instances.length).toBe(0); }); }); describe('scope has matching elements', () => { let testScope; let testElement1; let testElement2; beforeEach(() => { testScope = document.createElement('div'); testElement1 = document.createElement('div'); testElement2 = document.createElement('div'); testElement1.classList.add('util1'); testElement2.classList.add('util1'); testScope.appendChild(testElement1); testScope.appendChild(testElement2); }); it('should construct a utility instance', () => { const setupUtilities = utilRegistry.setup(TestUtil1, testScope); expect(setupUtilities).toBeTruthy(); expect(setupUtilities[0]).toBeTruthy(); }); it('should construct an instance for each matching element', () => { const setupUtilities = utilRegistry.setup(TestUtil1, testScope); expect(setupUtilities).toBeTruthy(); expect(setupUtilities[0].element).toBe(testElement1); expect(setupUtilities[1].element).toBe(testElement2); }); it('should pass the app instance', () => { const fakeApp = { }; utilRegistry.setApp(fakeApp); const setupUtilities = utilRegistry.setup(TestUtil1, testScope); expect(setupUtilities).toBeTruthy(); setupUtilities.forEach((setupUtility) => { expect(setupUtility).toBeTruthy(); expect(setupUtility.instance).toBeTruthy(); }); expect(setupUtilities[0].instance.app).toBe(fakeApp); expect(setupUtilities[1].instance.app).toBe(fakeApp); }); }); }); describe('deregister()', () => { let testScope; let testElement1; let testElement2; beforeEach(() => { testScope = document.createElement('div'); testElement1 = document.createElement('div'); testElement2 = document.createElement('div'); testElement1.classList.add('util1'); testElement2.classList.add('util1'); testScope.appendChild(testElement1); testScope.appendChild(testElement2); }); it('should remove util', () => { // register util utilRegistry.register(TestUtil1); let foundUtil = utilRegistry.find(TestUtil1.name); expect(foundUtil).toBeTruthy(); // deregister util utilRegistry.deregister(TestUtil1.name); foundUtil = utilRegistry.find(TestUtil1.name); expect(foundUtil).toBeFalsy(); }); it('should destroy util instances if requested', () => { utilRegistry.register(TestUtil1); let foundUtil = utilRegistry.find(TestUtil1.name); expect(foundUtil).toBeTruthy(); utilRegistry.setup(TestUtil1, testScope); let firstActiveUtil = utilRegistry._activeUtilInstancesWrapped[0]; expect(utilRegistry._activeUtilInstancesWrapped.length).toEqual(2); expect(utilRegistry._activeUtilInstancesWrapped[0].element).toEqual(testElement1); spyOn(firstActiveUtil.instance, 'destroy'); utilRegistry.deregister(TestUtil1.name, true); expect(utilRegistry._activeUtilInstancesWrapped[0]).toBeFalsy(); expect(firstActiveUtil.instance.destroy).toHaveBeenCalled(); }); }); describe('initAll()', () => { it('should setup all the utilities', () => { spyOn(utilRegistry, 'setup'); utilRegistry.register(TestUtil1); utilRegistry.register(TestUtil2); utilRegistry.register(TestUtil3); utilRegistry.initAll(); expect(utilRegistry.setup.calls.count()).toBe(3); expect(utilRegistry.setup.calls.argsFor(0)).toEqual([TestUtil1, document.body]); expect(utilRegistry.setup.calls.argsFor(1)).toEqual([TestUtil2, document.body]); expect(utilRegistry.setup.calls.argsFor(2)).toEqual([TestUtil3, document.body]); }); it('should pass the given scope', () => { spyOn(utilRegistry, 'setup'); utilRegistry.register(TestUtil1); const scope = document.createElement('div'); 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', () => { utilRegistry.register(TestUtil3); const initializedInstances = utilRegistry.initAll(testScope); expect(initializedInstances.length).toBe(2); }); it('should not start instances that do not provide a start function', () => { utilRegistry.register(TestUtil1); utilRegistry.register(TestUtil2); const startedInstances = utilRegistry.initAll(testScope); expect(startedInstances.length).toBe(0); }); }); }); describe('destroyAll()', () => { let testScope; let testElement; let firstUtil; beforeEach( () => { testScope = document.createElement('div'); testElement = document.createElement('div'); testElement.classList.add('util3'); testScope.appendChild(testElement); utilRegistry.register(TestUtil3); utilRegistry.initAll(testScope); firstUtil = utilRegistry._activeUtilInstancesWrapped[0]; spyOn(firstUtil.instance, 'destroy'); }); it('Util should be destroyed', () => { utilRegistry.destroyAll(testScope); expect(utilRegistry._activeUtilInstancesWrapped.length).toBe(0); expect(firstUtil.instance.destroy).toHaveBeenCalled(); }); it('Util out of scope should not be destroyed', () => { let outOfScope = document.createElement('div'); expect(utilRegistry._activeUtilInstancesWrapped.length).toEqual(1); utilRegistry.destroyAll(outOfScope); expect(utilRegistry._activeUtilInstancesWrapped.length).toEqual(1); expect(utilRegistry._activeUtilInstancesWrapped[0]).toBe(firstUtil); expect(firstUtil.instance.destroy).not.toHaveBeenCalled(); }); }); }); // test utilities @Utility({ selector: '.util1' }) class TestUtil1 { constructor(element, app) { this.element = element; this.app = app; } destroy() {} } @Utility({ selector: '#util2' }) class TestUtil2 { } @Utility({ selector: '.util3' }) class TestUtil3 { constructor() {} start() {} destroy() {} } @Utility({ selector: '#throws' }) class ThrowingUtil { constructor() { throw new Error(); } }