Repository: exadel-inc/esl
Pull request #1573 (2023-03-27 14:38:28)

feat(esl-utils): Support for ESLDomElementTarget as a target for ESLResizeObserverTarget
Target for ResizeObserverTarget with extended from 'Element' to being able to accept mixin elements.  #1562 

codeclimate[bot]: Code Climate has analyzed commit 71714ecd and detected **0 issues** on this pull request.

The test coverage on the diff in this pull request is **91.6%** (**50%** is the threshold).

This pull request will bring the total coverage in the repository to **48.4%** (**0.0%** change).

View more on [Code Climate](https://codeclimate.com/github/exadel-inc/esl/pull/1573).

codeclimate[bot]: Code Climate has analyzed commit 75975b22 and detected **0 issues** on this pull request.

The test coverage on the diff in this pull request is **91.6%** (**50%** is the threshold).

This pull request will bring the total coverage in the repository to **48.4%** (**0.0%** change).

View more on [Code Climate](https://codeclimate.com/github/exadel-inc/esl/pull/1573).

codeclimate[bot]: Code Climate has analyzed commit 107f474a and detected **0 issues** on this pull request.

The test coverage on the diff in this pull request is **91.6%** (**50%** is the threshold).

This pull request will bring the total coverage in the repository to **48.4%** (**0.0%** change).

View more on [Code Climate](https://codeclimate.com/github/exadel-inc/esl/pull/1573).

codeclimate[bot]: Code Climate has analyzed commit 0631b835 and detected **0 issues** on this pull request.

The test coverage on the diff in this pull request is **100.0%** (**50%** is the threshold).

This pull request will bring the total coverage in the repository to **48.5%** (**0.0%** change).

View more on [Code Climate](https://codeclimate.com/github/exadel-inc/esl/pull/1573).

codeclimate[bot]: Code Climate has analyzed commit 7b857a9f and detected **0 issues** on this pull request.

The test coverage on the diff in this pull request is **100.0%** (**50%** is the threshold).

This pull request will bring the total coverage in the repository to **48.6%** (**0.0%** change).

View more on [Code Climate](https://codeclimate.com/github/exadel-inc/esl/pull/1573).

codeclimate[bot]: Code Climate has analyzed commit 8885fc37 and detected **0 issues** on this pull request.

The test coverage on the diff in this pull request is **100.0%** (**50%** is the threshold).

This pull request will bring the total coverage in the repository to **48.6%** (**0.0%** change).

View more on [Code Climate](https://codeclimate.com/github/exadel-inc/esl/pull/1573).


Patch:
diff --git a/src/modules/esl-event-listener/core/targets/resize.adapter.ts b/src/modules/esl-event-listener/core/targets/resize.adapter.ts
index f1a593495..febd11bd2 100644
--- a/src/modules/esl-event-listener/core/targets/resize.adapter.ts
+++ b/src/modules/esl-event-listener/core/targets/resize.adapter.ts
@@ -1,6 +1,9 @@
 import {SyntheticEventTarget} from '../../../esl-utils/dom/events/target';
 import {ESLElementResizeEvent} from './resize.adapter.event';
 
+import {resolveDomTarget} from '../../../esl-utils/abstract/dom-target';
+import type {ESLDomElementTarget} from '../../../esl-utils/abstract/dom-target';
+
 /** Adapter class for {@link ResizeObserver} that implements {@link EventTarget} */
 export class ESLResizeObserverTarget extends SyntheticEventTarget {
   /** {@link ESLResizeObserverTarget} instances holder */
@@ -10,6 +13,9 @@ export class ESLResizeObserverTarget extends SyntheticEventTarget {
     changes.forEach(this.handleChange, this)
   );
 
+  /** Observed {@link Element} of the {@link ESLResizeObserverTarget} instance */
+  public readonly target: Element;
+
   /** Internal method to handle {@link ResizeObserver} entry change */
   protected static handleChange(
     this: typeof ESLResizeObserverTarget,
@@ -20,23 +26,22 @@ export class ESLResizeObserverTarget extends SyntheticEventTarget {
     adapter.dispatchEvent(ESLElementResizeEvent.fromEntry(entry));
   }
 
-  /** Creates {@link ESLResizeObserverTarget} instance for the {@link Element} */
-  public static create(target: Element): ESLResizeObserverTarget {
+  /** Creates {@link ESLResizeObserverTarget} instance for the {@link ESLDomElementTarget} */
+  public static create(target: ESLDomElementTarget): ESLResizeObserverTarget {
     return new ESLResizeObserverTarget(target);
   }
 
   /**
-   * Creates {@link ESLResizeObserverTarget} for the {@link Element}.
+   * Creates {@link ESLResizeObserverTarget} for the {@link ESLDomElementTarget}.
    * Note the {@link ESLResizeObserverTarget} instances are singletons relatively to the {@link Element}
    */
-  protected constructor(
-    /** Observed {@link Element} of the {@link ESLResizeObserverTarget} instance */
-    public readonly target: Element
-  ) {
+  protected constructor(target: ESLDomElementTarget) {
+    target = resolveDomTarget(target);
     const instance = ESLResizeObserverTarget.mapping.get(target);
     if (instance) return instance;
     super();
-    ESLResizeObserverTarget.mapping.set(target, this);
+    this.target = target;
+    ESLResizeObserverTarget.mapping.set(this.target, this);
   }
 
   /** Subscribes to the observed target {@link Element} changes */


Test patch:
diff --git a/src/modules/esl-event-listener/test/targets/resize.test.ts b/src/modules/esl-event-listener/test/targets/resize.test.ts
index ba49059bc..e25203751 100644
--- a/src/modules/esl-event-listener/test/targets/resize.test.ts
+++ b/src/modules/esl-event-listener/test/targets/resize.test.ts
@@ -17,37 +17,79 @@ describe('ESLEventUtils: ResizeObserver EventTarget adapter', () => {
   });
 
   describe('ESLResizeObserverTarget livecycle', () => {
-    const mock = getLastResizeObserverMock();
-    const el = document.createElement('div');
-    const target = ESLEventUtils.resize(el);
-
-    const cb1 = jest.fn();
-    const cb2 = jest.fn();
-
-    beforeEach(() => {
-      mock.observe.mockReset();
-      mock.unobserve.mockReset();
+    describe('Element as a taget', () => {
+      const mock = getLastResizeObserverMock();
+      const el = document.createElement('div');
+      const target = ESLEventUtils.resize(el);
+
+      const cb1 = jest.fn();
+      const cb2 = jest.fn();
+
+      beforeEach(() => {
+        mock.observe.mockReset();
+        mock.unobserve.mockReset();
+      });
+
+      test('Subscription produces ResizeObserver interaction', () => {
+        target.addEventListener(cb1);
+        expect(mock.observe).lastCalledWith(el);
+        expect(mock.unobserve).not.toBeCalled();
+      });
+      test('Second subscription does not produces ResizeObserver interaction', () => {
+        target.addEventListener(cb2);
+        expect(mock.observe).not.toBeCalled();
+        expect(mock.unobserve).not.toBeCalled();
+      });
+      test('Single unsubscription does not produces internal unsubscription', () => {
+        target.removeEventListener(cb2);
+        expect(mock.observe).not.toBeCalled();
+        expect(mock.unobserve).not.toBeCalled();
+      });
+      test('Removal of all of subscriptions produces internal unsubscription', () => {
+        target.removeEventListener(cb1);
+        expect(mock.observe).not.toBeCalled();
+        expect(mock.unobserve).toBeCalled();
+      });
     });
 
-    test('Subscription produces ResizeObserver interaction', () => {
-      target.addEventListener(cb1);
-      expect(mock.observe).lastCalledWith(el);
-      expect(mock.unobserve).not.toBeCalled();
-    });
-    test('Second subscription does not produces ResizeObserver interaction', () => {
-      target.addEventListener(cb2);
-      expect(mock.observe).not.toBeCalled();
-      expect(mock.unobserve).not.toBeCalled();
-    });
-    test('Single unsubscription does not produces internal unsubscription', () => {
-      target.removeEventListener(cb2);
-      expect(mock.observe).not.toBeCalled();
-      expect(mock.unobserve).not.toBeCalled();
-    });
-    test('Remove of all of subscriptions produce internal unsubscription', () => {
-      target.removeEventListener(cb1);
-      expect(mock.observe).not.toBeCalled();
-      expect(mock.unobserve).toBeCalled();
+    describe('ESLDomElementRelated as a taget', () => {
+      const mock = getLastResizeObserverMock();
+      const el = document.createElement('div');
+      const mixin = {$host: el};
+      const target = ESLEventUtils.resize(el);
+      const targetMixin = ESLEventUtils.resize(mixin);
+
+      const cb1 = jest.fn();
+      const cb2 = jest.fn();
+
+      beforeEach(() => {
+        mock.observe.mockReset();
+        mock.unobserve.mockReset();
+      });
+
+      test('Should be only one instance for ESLResizeObserverTarget and it`s host', () => {
+        expect(targetMixin).toBe(target);
+      });
+      test('ESLDomElementRelated subscription produces ResizeObserver interaction', () => {
+        targetMixin.addEventListener(cb1);
+        expect(mock.observe).lastCalledWith(el);
+        expect(mock.unobserve).not.toBeCalled();
+      });
+      test('Repeated subscription of ESLDomElementRelated host does not produces ResizeObserver interaction', () => {
+        target.addEventListener(cb2);
+        expect(mock.observe).not.toBeCalled();
+        expect(mock.unobserve).not.toBeCalled();
+      });
+      test('Single unsubscription does not produces internal unsubscription', () => {
+        targetMixin.removeEventListener(cb1);
+        expect(mock.observe).not.toBeCalled();
+        expect(mock.unobserve).not.toBeCalled();
+      });
+      test('Removal of all of subscriptions produces internal unsubscription', () => {
+        target.removeEventListener(cb2);
+        expect(mock.observe).not.toBeCalled();
+        expect(mock.unobserve).toBeCalled();
+      });
     });
   });
 
@@ -56,6 +98,10 @@ describe('ESLEventUtils: ResizeObserver EventTarget adapter', () => {
 
     const el1 = document.createElement('div');
     const el2 = document.createElement('div');
+    const el3 = document.createElement('div');
+    const mixin = {
+      $host: el3
+    };
 
     const cb1_1 = jest.fn();
     ESLEventUtils.resize(el1).addEventListener(cb1_1);
@@ -69,6 +115,9 @@ describe('ESLEventUtils: ResizeObserver EventTarget adapter', () => {
     ESLEventUtils.resize(el2).addEventListener(cb2_1);
     expect(cb2_1).not.toBeCalled();
 
+    const cb3_1 = jest.fn();
+    ESLEventUtils.resize(mixin).addEventListener(cb3_1);
+
     const fakeEntry = (el: Element) => ({
       target: el,
       contentRect: el.getBoundingClientRect(),
@@ -81,6 +130,7 @@ describe('ESLEventUtils: ResizeObserver EventTarget adapter', () => {
       cb1_1.mockReset();
       cb1_2.mockReset();
       cb2_1.mockReset();
+      cb3_1.mockReset();
     });
 
     test('Dispatched change received by all subscribers', () => {
@@ -90,6 +140,7 @@ describe('ESLEventUtils: ResizeObserver EventTarget adapter', () => {
       expect(cb1_1).toBeCalled();
       expect(cb1_2).toBeCalled();
       expect(cb2_1).not.toBeCalled();
+      expect(cb3_1).not.toBeCalled();
     });
 
     test('Dispatched change received by correct target', () => {
@@ -99,6 +150,7 @@ describe('ESLEventUtils: ResizeObserver EventTarget adapter', () => {
       expect(cb2_1).toBeCalled();
       expect(cb1_1).not.toBeCalled();
       expect(cb1_2).not.toBeCalled();
+      expect(cb3_1).not.toBeCalled();
     });
 
     test('Dispatched change produces an Event instance', () => {
@@ -126,5 +178,12 @@ describe('ESLEventUtils: ResizeObserver EventTarget adapter', () => {
       mock.callback.call(mock, [entry]);
       expect(cb2_1).lastCalledWith(expect.objectContaining({target: el2}));
     });
+
+    test('Dispatched change produces correct event target for ESLDomElementRelated', () => {
+      const entry: ResizeObserverEntry = fakeEntry(el3);
+
+      mock.callback.call(mock, [entry]);
+      expect(cb3_1).lastCalledWith(expect.objectContaining({target: el3}));
+    });
   });
 });