65 lines
1.8 KiB
TypeScript
65 lines
1.8 KiB
TypeScript
import { describe, it, expect, afterEach } from 'vitest';
|
|
|
|
const { clickOutside } = await import('./clickOutside');
|
|
|
|
describe('clickOutside action', () => {
|
|
const nodes: HTMLElement[] = [];
|
|
|
|
function makeNode(): HTMLElement {
|
|
const node = document.createElement('div');
|
|
document.body.appendChild(node);
|
|
nodes.push(node);
|
|
return node;
|
|
}
|
|
|
|
afterEach(() => {
|
|
nodes.forEach((n) => n.remove());
|
|
nodes.length = 0;
|
|
});
|
|
|
|
it('registers a capture-phase click listener on mount', () => {
|
|
const node = makeNode();
|
|
const original = document.addEventListener.bind(document);
|
|
let registered = false;
|
|
document.addEventListener = (type: string, _fn: unknown, opts: unknown) => {
|
|
if (type === 'click' && opts === true) registered = true;
|
|
original(type as string, _fn as EventListener, opts as boolean);
|
|
};
|
|
clickOutside(node);
|
|
expect(registered).toBe(true);
|
|
document.addEventListener = original;
|
|
});
|
|
|
|
it('dispatches clickoutside when clicking outside the node', () => {
|
|
const node = makeNode();
|
|
const outside = makeNode();
|
|
let fired = false;
|
|
node.addEventListener('clickoutside', () => (fired = true));
|
|
clickOutside(node);
|
|
outside.click();
|
|
expect(fired).toBe(true);
|
|
});
|
|
|
|
it('does not dispatch clickoutside when clicking inside the node', () => {
|
|
const node = makeNode();
|
|
const child = document.createElement('span');
|
|
node.appendChild(child);
|
|
let fired = false;
|
|
node.addEventListener('clickoutside', () => (fired = true));
|
|
clickOutside(node);
|
|
child.click();
|
|
expect(fired).toBe(false);
|
|
});
|
|
|
|
it('removes the listener on destroy', () => {
|
|
const node = makeNode();
|
|
const outside = makeNode();
|
|
let count = 0;
|
|
node.addEventListener('clickoutside', () => count++);
|
|
const { destroy } = clickOutside(node);
|
|
destroy();
|
|
outside.click();
|
|
expect(count).toBe(0);
|
|
});
|
|
});
|