Skip to content

Commit

Permalink
fix(esl-event-listener): fix delegation handling for improper targets
Browse files Browse the repository at this point in the history
  • Loading branch information
abarmina committed Mar 1, 2024
1 parent 717794c commit 127297c
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 20 deletions.
2 changes: 1 addition & 1 deletion src/modules/esl-event-listener/core/listener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export class ESLEventListener implements ESLListenerDefinition, EventListenerObj
if (!isElement(target)) return;

const $delegate = target.closest(delegate);
if (isElement(currentTarget) && !currentTarget.contains($delegate)) return;
if (!isElement($delegate) || isElement(currentTarget) && !currentTarget.contains($delegate)) return;

handler(Object.assign(e, {$delegate}));
}
Expand Down
45 changes: 26 additions & 19 deletions src/modules/esl-event-listener/test/listener.delegate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,66 +17,73 @@ describe('ESlEventListener subscription and delegation', () => {
test('Simple click subscription catches click', () => {
const handler = jest.fn();
ESLEventUtils.subscribe(host, 'click', handler);
expect(handler).toBeCalledTimes(0);
expect(handler).toHaveBeenCalledTimes(0);
btn.click();
expect(handler).toBeCalledTimes(1);
expect(handler).toHaveBeenCalledTimes(1);
btn2.click();
expect(handler).toBeCalledTimes(2);
expect(handler).toHaveBeenCalledTimes(2);
});

test('Subscription with selector catches click exact on selected target', () => {
const handler = jest.fn();
ESLEventUtils.subscribe(host, {event: 'click', selector: '.btn'}, handler);
expect(handler).toBeCalledTimes(0);
expect(handler).toHaveBeenCalledTimes(0);
btn.click();
expect(handler).toBeCalledTimes(1);
expect(handler).toHaveBeenCalledTimes(1);
btn2.click();
expect(handler).toBeCalledTimes(1);
expect(handler).toHaveBeenCalledTimes(1);
});

test('Subscription with selector catches click inside selected target', () => {
const handler = jest.fn();
ESLEventUtils.subscribe(host, {event: 'click', selector: '.btn'}, handler);
expect(handler).toBeCalledTimes(0);
expect(handler).toHaveBeenCalledTimes(0);
btnSpan.click();
expect(handler).toBeCalledTimes(1);
expect(handler).toHaveBeenCalledTimes(1);
});

test('Subscription with target provided with query catches click', () => {
const handler = jest.fn();
ESLEventUtils.subscribe(host, {event: 'click', target: '::find(#btn)'}, handler);
expect(handler).toBeCalledTimes(0);
expect(handler).toHaveBeenCalledTimes(0);
btnSpan.click();
expect(handler).toBeCalledTimes(0);
expect(handler).toHaveBeenCalledTimes(0);
btn2.click();
expect(handler).toBeCalledTimes(1);
expect(handler).toHaveBeenCalledTimes(1);
});

test('Subscription with target provided by instance', () => {
const handler = jest.fn();
const el = document.createElement('button');
ESLEventUtils.subscribe(host, {event: 'click', target: el}, handler);
expect(handler).toBeCalledTimes(0);
expect(handler).toHaveBeenCalledTimes(0);
btn.click();
expect(handler).toBeCalledTimes(0);
expect(handler).toHaveBeenCalledTimes(0);
btn2.click();
expect(handler).toBeCalledTimes(0);
expect(handler).toHaveBeenCalledTimes(0);
el.click();
expect(handler).toBeCalledTimes(1);
expect(handler).toHaveBeenCalledTimes(1);
});

test('Click on the target element leads to correct delegate information', () => {
const handler = jest.fn();
ESLEventUtils.subscribe(host, {event: 'click', selector: '.btn'}, handler);
btn.click();
expect(handler).toBeCalledWith(expect.objectContaining({$delegate: btn}));
expect(handler).toHaveBeenCalledWith(expect.objectContaining({$delegate: btn}));
});

test('Click inside the target element leads to correct delegate information', () => {
const handler = jest.fn();
ESLEventUtils.subscribe(host, {event: 'click', selector: '.btn'}, handler);
btnSpan.click();
expect(handler).toBeCalledWith(expect.objectContaining({$delegate: btn}));
expect(handler).toHaveBeenCalledWith(expect.objectContaining({$delegate: btn}));
});

test('Click on the container should not be handled if a selector is defined', () => {
const handler = jest.fn();
ESLEventUtils.subscribe(host, {event: 'click', target: document, selector: '#btn'}, handler);
document.body.click();
expect(handler).not.toHaveBeenCalled();
});

describe('Delegation on non DOM target works correctly', () => {
Expand All @@ -87,14 +94,14 @@ describe('ESlEventListener subscription and delegation', () => {
const handler = jest.fn();
ESLEventUtils.subscribe(host, {event: 'click', target: document, selector: 'button'}, handler);
$btn.click();
expect(handler).toBeCalledWith(expect.objectContaining({$delegate: $btn}));
expect(handler).toHaveBeenCalledWith(expect.objectContaining({$delegate: $btn}));
});

test('Delegation of the click event on the window works correct', () => {
const handler = jest.fn();
ESLEventUtils.subscribe(host, {event: 'click', target: window, selector: 'button'}, handler);
$btn.click();
expect(handler).toBeCalledWith(expect.objectContaining({$delegate: $btn}));
expect(handler).toHaveBeenCalledWith(expect.objectContaining({$delegate: $btn}));
});
});
});

0 comments on commit 127297c

Please sign in to comment.