Repository: exadel-inc/esl
Pull request #1251 (2022-09-28 22:15:00)

fix(esl-event-listener): allow to subscribe listener by global selector without host instanceof HTMLElement


Patch:
diff --git a/src/modules/esl-event-listener/core/api.ts b/src/modules/esl-event-listener/core/api.ts
index 6ca892848..e88845787 100644
--- a/src/modules/esl-event-listener/core/api.ts
+++ b/src/modules/esl-event-listener/core/api.ts
@@ -66,7 +66,7 @@ export class ESLEventUtils {
 
     const listeners = ESLEventListener.createOrResolve(host, handler, eventDesc as ESLListenerDescriptor);
     const subscribed = listeners.filter((listener) => listener.subscribe());
-    if (!subscribed.length) console.warn('[ESL]: Empty subscription %o for %o', eventDesc, handler);
+    if (!subscribed.length) console.warn('[ESL]: Empty subscription %o', Object.assign({}, eventDesc, {handler}));
     return subscribed;
   }
 
diff --git a/src/modules/esl-event-listener/core/listener.ts b/src/modules/esl-event-listener/core/listener.ts
index bf8b9010b..ff01fe742 100644
--- a/src/modules/esl-event-listener/core/listener.ts
+++ b/src/modules/esl-event-listener/core/listener.ts
@@ -67,9 +67,8 @@ export class ESLEventListener implements ESLListenerDefinition, EventListenerObj
     const target = resolveProperty(this.target, this.host);
     if (isObject(target)) return wrap(target);
     const $host  = '$host' in this.host ? this.host.$host : this.host;
-    if (!($host instanceof HTMLElement)) return [];
-    if (typeof target === 'undefined') return [$host];
     if (typeof target === 'string') return ESLTraversingQuery.all(target, $host);
+    if (typeof target === 'undefined' && $host instanceof HTMLElement) return [$host];
     return [];
   }
 


Test patch:
diff --git a/src/modules/esl-event-listener/test/listener.subscribe.test.ts b/src/modules/esl-event-listener/test/listener.subscribe.test.ts
index ae473e493..bc32bc9da 100644
--- a/src/modules/esl-event-listener/test/listener.subscribe.test.ts
+++ b/src/modules/esl-event-listener/test/listener.subscribe.test.ts
@@ -6,6 +6,7 @@ describe('ESLEventUtils:subscribe tests', () => {
     const handle = jest.fn();
     ESLEventUtils.subscribe($host, {event: 'click'}, handle);
     expect(ESLEventUtils.listeners($host).length).toBe(1);
+    ESLEventUtils.unsubscribe($host);
   });
 
   test('ESLEventUtils.subscribe successfully subscribes listener by event name', () => {
@@ -13,6 +14,7 @@ describe('ESLEventUtils:subscribe tests', () => {
     const handle = jest.fn();
     ESLEventUtils.subscribe($host, 'click', handle);
     expect(ESLEventUtils.listeners($host).length).toBe(1);
+    ESLEventUtils.unsubscribe($host);
   });
 
   test('ESLEventUtils.subscribe successfully subscribes listener by event provider', () => {
@@ -25,6 +27,24 @@ describe('ESLEventUtils:subscribe tests', () => {
     ESLEventUtils.subscribe($host, {event: provider}, handle);
     expect(ESLEventUtils.listeners($host).length).toBe(1);
     expect(provider).toBeCalledWith($host);
+    ESLEventUtils.unsubscribe($host);
+  });
+
+  test('ESLEventListener subscribes successfully by global selector',  () => {
+    const host = {};
+    const handle = jest.fn();
+    ESLEventUtils.subscribe(host, {event: 'click', target: 'body'}, handle);
+    expect(ESLEventUtils.listeners(host).length).toBe(1);
+    ESLEventUtils.unsubscribe(host);
+  });
+
+  test('ESLEventListener subscribes successfully by target instance',  () => {
+    const host = {};
+    const el = document.createElement('div');
+    const handle = jest.fn();
+    ESLEventUtils.subscribe(host, {event: 'click', target: el}, handle);
+    expect(ESLEventUtils.listeners(host).length).toBe(1);
+    ESLEventUtils.unsubscribe(host);
   });
 
   test('ESLEventUtils.subscribe successfully subscribes listeners by string with multiple events', () => {
@@ -34,6 +54,7 @@ describe('ESLEventUtils:subscribe tests', () => {
     expect(ESLEventUtils.listeners($host).length).toBe(2);
     expect(ESLEventUtils.listeners($host, 'keydown').length).toBe(1);
     expect(ESLEventUtils.listeners($host, 'click').length).toBe(1);
+    ESLEventUtils.unsubscribe($host);
   });
 
   test('ESLEventListener observes target events', () => {
@@ -42,5 +63,14 @@ describe('ESLEventUtils:subscribe tests', () => {
     ESLEventUtils.subscribe($host, {event: 'click'}, handle);
     $host.click();
     expect(handle).toBeCalledTimes(1);
+    ESLEventUtils.unsubscribe($host);
+  });
+
+  test('ESLEventListener does not subscribe if no targets',  () => {
+    jest.spyOn(console, 'warn').mockImplementationOnce(() => {});
+    const host = {};
+    const handle = jest.fn();
+    ESLEventUtils.subscribe(host, {event: 'click'}, handle);
+    expect(ESLEventUtils.listeners(host).length).toBe(0);
   });
 });