TransFlow/node_modules/v-click-outside-x/__tests__/v-click-outside-x.test.js

408 lines
12 KiB
JavaScript

import PACKAGE_JSON from 'RootDir/package';
import * as ESM from 'src/index';
import * as WEB from 'dist/v-click-outside-x';
import * as MIN from 'dist/v-click-outside-x.min';
const ESMREQ = require('src/index');
const WEBREQ = require('dist/v-click-outside-x');
const MINREQ = require('dist/v-click-outside-x.min');
const namePrefix = 'vClickOutside';
const methods = [
{method: ESM, name: `${namePrefix} ESM`},
{method: WEB, name: `${namePrefix} WEB`},
{method: MIN, name: `${namePrefix} MIN`},
{method: ESMREQ, name: `${namePrefix} ESMREQ`},
{method: WEBREQ, name: `${namePrefix} WEBREQ`},
{method: MINREQ, name: `${namePrefix} MINREQ`},
{method: ESM, name: `${namePrefix} ESM no document`, noDoc: true},
];
const doc = window.document;
methods.forEach(({method, name, noDoc}) => {
const {directive, install} = method;
let calls = 1;
describe(`${name}`, () => {
beforeAll(() => {
if (noDoc) {
calls = 0;
delete window.document;
}
});
beforeEach(() => {
doc.addEventListener = jest.fn();
doc.removeEventListener = jest.fn();
});
afterEach(() => {
doc.addEventListener = undefined;
doc.removeEventListener = undefined;
});
describe('plugin', () => {
it('the directive is an object', () => {
expect.assertions(1);
expect(directive).toBeInstanceOf(Object);
});
it('it has all hook functions available', () => {
expect.assertions(2);
['bind', 'unbind'].forEach(functionName => {
expect(directive[functionName]).toBeInstanceOf(Function);
});
});
it('$_captureInstances is an empty Map', () => {
expect.assertions(1);
expect(Object.keys(directive.$_captureInstances)).toHaveLength(0);
});
it('$_nonCaptureInstances is an empty Map', () => {
expect.assertions(1);
expect(Object.keys(directive.$_nonCaptureInstances)).toHaveLength(0);
});
it('$_onCaptureEvent to be a function', () => {
expect.assertions(1);
expect(directive.$_onCaptureEvent).toBeInstanceOf(Function);
});
it('$_onNonCaptureEvent to be a function', () => {
expect.assertions(1);
expect(directive.$_onNonCaptureEvent).toBeInstanceOf(Function);
});
it('version to be a string', () => {
expect.assertions(1);
expect(typeof directive.version).toStrictEqual('string');
});
it('version to be as per package.json', () => {
expect.assertions(1);
expect(directive.version).toStrictEqual(PACKAGE_JSON.version);
});
it('version to be enumerable', () => {
expect.assertions(1);
expect(
Object.prototype.propertyIsEnumerable.call(directive, 'version'),
).toBe(true);
});
it('install the directive into the vue instance', () => {
expect.assertions(2);
const vue = {
directive: jest.fn(),
};
install(vue);
expect(vue.directive).toHaveBeenCalledWith('click-outside', directive);
expect(vue.directive).toHaveBeenCalledTimes(1);
});
});
describe('directive', () => {
describe('bind/unbind', () => {
describe('bind exceptions', () => {
it('throws an error if value is not a function', () => {
expect.assertions(1);
const div1 = doc.createElement('div');
const bindWithNoFunction = () => directive.bind(div1, {});
expect(bindWithNoFunction).toThrowErrorMatchingSnapshot();
});
});
describe('single', () => {
const div1 = doc.createElement('div');
it('adds to the list and event listener', () => {
expect.assertions(6);
const eventHandler = jest.fn();
directive.bind(div1, {value: eventHandler});
expect(Object.keys(directive.$_nonCaptureInstances)).toHaveLength(
1,
);
expect(directive.$_nonCaptureInstances).toHaveProperty('click');
const clickInstances = directive.$_nonCaptureInstances.click;
expect(clickInstances).toBeInstanceOf(Array);
expect(clickInstances).toHaveLength(1);
expect(clickInstances.find(item => item.el === div1)).toBeDefined();
expect(doc.addEventListener.mock.calls).toHaveLength(calls);
});
it('removes from the list and event listener', () => {
expect.assertions(2);
directive.unbind(div1);
expect(Object.keys(directive.$_nonCaptureInstances)).toHaveLength(
0,
);
expect(doc.removeEventListener.mock.calls).toHaveLength(calls);
});
});
describe('multiple', () => {
const div1 = doc.createElement('div');
const div2 = doc.createElement('div');
it('adds to the list and event listener', () => {
expect.assertions(7);
const eventHandler1 = jest.fn();
const eventHandler2 = jest.fn();
directive.bind(div1, {value: eventHandler1});
directive.bind(div2, {arg: 'click', value: eventHandler2});
expect(Object.keys(directive.$_nonCaptureInstances)).toHaveLength(
1,
);
expect(directive.$_nonCaptureInstances).toHaveProperty('click');
const clickInstances = directive.$_nonCaptureInstances.click;
expect(clickInstances).toBeInstanceOf(Array);
expect(clickInstances).toHaveLength(2);
expect(clickInstances.find(item => item.el === div1)).toBeDefined();
expect(clickInstances.find(item => item.el === div2)).toBeDefined();
expect(doc.addEventListener.mock.calls).toHaveLength(calls);
});
it('removes from the list and the event listener', () => {
expect.assertions(7);
directive.unbind(div1);
expect(Object.keys(directive.$_nonCaptureInstances)).toHaveLength(
1,
);
expect(directive.$_nonCaptureInstances).toHaveProperty('click');
const clickInstances = directive.$_nonCaptureInstances.click;
expect(clickInstances).toBeInstanceOf(Array);
expect(clickInstances).toHaveLength(1);
expect(clickInstances.find(item => item.el === div2)).toBeDefined();
directive.unbind(div2);
expect(Object.keys(directive.$_nonCaptureInstances)).toHaveLength(
0,
);
expect(doc.removeEventListener.mock.calls).toHaveLength(calls);
});
});
describe('bind', () => {
it('saves the instance binding and element', () => {
expect.assertions(11);
const div1 = doc.createElement('div');
const div2 = doc.createElement('div');
const div3 = doc.createElement('div');
const eventHandler1 = jest.fn();
const eventHandler2 = jest.fn();
directive.bind(div1, {
arg: 'pointerdown',
modifiers: {capture: true},
value: eventHandler1,
});
directive.bind(div2, {
arg: 'pointerdown',
modifiers: {stop: true},
value: eventHandler2,
});
directive.bind(div3, {
arg: 'pointerdown',
modifiers: {prevent: true},
value: eventHandler2,
});
expect(Object.keys(directive.$_captureInstances)).toHaveLength(1);
expect(directive.$_captureInstances).toHaveProperty('pointerdown');
const clickCaptureInstances =
directive.$_captureInstances.pointerdown;
expect(clickCaptureInstances).toBeInstanceOf(Array);
expect(clickCaptureInstances).toHaveLength(1);
expect(
clickCaptureInstances.find(item => item.el === div1),
).toStrictEqual({
binding: {
arg: 'pointerdown',
modifiers: {
capture: true,
prevent: false,
stop: false,
},
value: eventHandler1,
},
el: div1,
});
expect(Object.keys(directive.$_nonCaptureInstances)).toHaveLength(
1,
);
expect(directive.$_nonCaptureInstances).toHaveProperty(
'pointerdown',
);
const clickNonCaptureInstances =
directive.$_nonCaptureInstances.pointerdown;
expect(clickNonCaptureInstances).toBeInstanceOf(Array);
expect(clickNonCaptureInstances).toHaveLength(2);
expect(
clickNonCaptureInstances.find(item => item.el === div2),
).toStrictEqual({
binding: {
arg: 'pointerdown',
modifiers: {
capture: false,
prevent: false,
stop: true,
},
value: eventHandler2,
},
el: div1,
});
expect(
clickNonCaptureInstances.find(item => item.el === div3),
).toStrictEqual({
binding: {
arg: 'pointerdown',
modifiers: {
capture: false,
prevent: true,
stop: false,
},
value: eventHandler2,
},
el: div1,
});
directive.unbind(div1);
directive.unbind(div2);
directive.unbind(div3);
});
});
});
describe('$_onCaptureEvent', () => {
const div1 = doc.createElement('div');
const span = doc.createElement('span');
div1.appendChild(span);
it('calls the callback if the element is not the same and does not contain the event target', () => {
expect.assertions(10);
const a = doc.createElement('a');
const event = {
preventDefault: jest.fn(),
stopPropagation: jest.fn(),
target: a,
};
const eventHandler1 = jest.fn();
directive.bind(div1, {value: eventHandler1});
directive.$_onNonCaptureEvent(event);
expect(eventHandler1).toHaveBeenCalledWith(event);
expect(eventHandler1.mock.instances).toHaveLength(1);
expect(eventHandler1.mock.instances[0]).toBe(directive);
expect(event.preventDefault).not.toHaveBeenCalled();
expect(event.stopPropagation).not.toHaveBeenCalled();
directive.unbind(div1);
const eventHandler2 = jest.fn();
directive.bind(div1, {
arg: 'touchdown',
modifiers: {capture: true, prevent: true, stop: true},
value: eventHandler2,
});
directive.$_onCaptureEvent(event);
expect(eventHandler2).toHaveBeenCalledWith(event);
expect(eventHandler2.mock.instances).toHaveLength(1);
expect(eventHandler2.mock.instances[0]).toBe(directive);
expect(event.preventDefault).toHaveBeenCalled();
expect(event.stopPropagation).toHaveBeenCalled();
directive.unbind(div1);
});
it('does not execute the callback if the event target its the element from the instance', () => {
expect.assertions(2);
const event = {
target: div1,
};
const eventHandler = jest.fn();
directive.bind(div1, {value: eventHandler});
directive.$_onNonCaptureEvent(event);
expect(eventHandler).not.toHaveBeenCalled();
expect(eventHandler.mock.instances).toHaveLength(0);
directive.unbind(div1);
});
it('does not execute the callback if the event target is contained in the element from the instance', () => {
expect.assertions(2);
const event = {
target: span,
};
const eventHandler = jest.fn();
directive.bind(div1, {value: eventHandler});
directive.$_onNonCaptureEvent(event);
expect(eventHandler).not.toHaveBeenCalled();
expect(eventHandler.mock.instances).toHaveLength(0);
directive.unbind(div1);
});
});
});
});
});