UNPKG

@testing-library/user-event

Version:
104 lines (100 loc) 5.36 kB
'use strict'; var options = require('../../options.js'); var getWindow = require('../misc/getWindow.js'); var isElementType = require('../misc/isElementType.js'); var level = require('../misc/level.js'); function hasPointerEvents(instance, element) { var _checkPointerEvents; return ((_checkPointerEvents = checkPointerEvents(instance, element)) === null || _checkPointerEvents === undefined ? undefined : _checkPointerEvents.pointerEvents) !== 'none'; } function closestPointerEventsDeclaration(element) { const window = getWindow.getWindow(element); for(let el = element, tree = []; el === null || el === undefined ? undefined : el.ownerDocument; el = el.parentElement){ tree.push(el); const pointerEvents = window.getComputedStyle(el).pointerEvents; if (pointerEvents && ![ 'inherit', 'unset' ].includes(pointerEvents)) { return { pointerEvents, tree }; } } return undefined; } const PointerEventsCheck = Symbol('Last check for pointer-events'); function checkPointerEvents(instance, element) { const lastCheck = element[PointerEventsCheck]; const needsCheck = instance.config.pointerEventsCheck !== options.PointerEventsCheckLevel.Never && (!lastCheck || hasBitFlag(instance.config.pointerEventsCheck, options.PointerEventsCheckLevel.EachApiCall) && lastCheck[level.ApiLevel.Call] !== level.getLevelRef(instance, level.ApiLevel.Call) || hasBitFlag(instance.config.pointerEventsCheck, options.PointerEventsCheckLevel.EachTrigger) && lastCheck[level.ApiLevel.Trigger] !== level.getLevelRef(instance, level.ApiLevel.Trigger)); if (!needsCheck) { return lastCheck === null || lastCheck === undefined ? undefined : lastCheck.result; } const declaration = closestPointerEventsDeclaration(element); element[PointerEventsCheck] = { [level.ApiLevel.Call]: level.getLevelRef(instance, level.ApiLevel.Call), [level.ApiLevel.Trigger]: level.getLevelRef(instance, level.ApiLevel.Trigger), result: declaration }; return declaration; } function assertPointerEvents(instance, element) { const declaration = checkPointerEvents(instance, element); if ((declaration === null || declaration === undefined ? undefined : declaration.pointerEvents) === 'none') { throw new Error([ `Unable to perform pointer interaction as the element ${declaration.tree.length > 1 ? 'inherits' : 'has'} \`pointer-events: none\`:`, '', printTree(declaration.tree) ].join('\n')); } } function printTree(tree) { return tree.reverse().map((el, i)=>[ ''.padEnd(i), el.tagName, el.id && `#${el.id}`, el.hasAttribute('data-testid') && `(testId=${el.getAttribute('data-testid')})`, getLabelDescr(el), tree.length > 1 && i === 0 && ' <-- This element declared `pointer-events: none`', tree.length > 1 && i === tree.length - 1 && ' <-- Asserted pointer events here' ].filter(Boolean).join('')).join('\n'); } function getLabelDescr(element) { var _element_labels; let label; if (element.hasAttribute('aria-label')) { label = element.getAttribute('aria-label'); } else if (element.hasAttribute('aria-labelledby')) { var _element_ownerDocument_getElementById_textContent, _element_ownerDocument_getElementById; label = (_element_ownerDocument_getElementById = element.ownerDocument.getElementById(element.getAttribute('aria-labelledby'))) === null || _element_ownerDocument_getElementById === undefined ? undefined : (_element_ownerDocument_getElementById_textContent = _element_ownerDocument_getElementById.textContent) === null || _element_ownerDocument_getElementById_textContent === undefined ? undefined : _element_ownerDocument_getElementById_textContent.trim(); } else if (isElementType.isElementType(element, [ 'button', 'input', 'meter', 'output', 'progress', 'select', 'textarea' ]) && ((_element_labels = element.labels) === null || _element_labels === undefined ? undefined : _element_labels.length)) { label = Array.from(element.labels).map((el)=>{ var _el_textContent; return (_el_textContent = el.textContent) === null || _el_textContent === undefined ? undefined : _el_textContent.trim(); }).join('|'); } else if (isElementType.isElementType(element, 'button')) { var _element_textContent; label = (_element_textContent = element.textContent) === null || _element_textContent === undefined ? undefined : _element_textContent.trim(); } label = label === null || label === undefined ? undefined : label.replace(/\n/g, ' '); if (Number(label === null || label === undefined ? undefined : label.length) > 30) { label = `${label === null || label === undefined ? undefined : label.substring(0, 29)}…`; } return label ? `(label=${label})` : ''; } // With the eslint rule and prettier the bitwise operation isn't nice to read function hasBitFlag(conf, flag) { // eslint-disable-next-line no-bitwise return (conf & flag) > 0; } exports.assertPointerEvents = assertPointerEvents; exports.hasPointerEvents = hasPointerEvents;