123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- "use strict";
- Object.defineProperty(exports, "__esModule", {
- value: true
- });
- exports.isFocusable = isFocusable;
- exports.isClickableInput = isClickableInput;
- exports.getMouseEventOptions = getMouseEventOptions;
- exports.isLabelWithInternallyDisabledControl = isLabelWithInternallyDisabledControl;
- exports.getActiveElement = getActiveElement;
- exports.calculateNewValue = calculateNewValue;
- exports.setSelectionRangeIfNecessary = setSelectionRangeIfNecessary;
- exports.eventWrapper = eventWrapper;
- exports.isValidDateValue = isValidDateValue;
- exports.isValidInputTimeValue = isValidInputTimeValue;
- exports.buildTimeValue = buildTimeValue;
- exports.getValue = getValue;
- exports.getSelectionRange = getSelectionRange;
- exports.isContentEditable = isContentEditable;
- exports.isInstanceOfElement = isInstanceOfElement;
- exports.isVisible = isVisible;
- exports.FOCUSABLE_SELECTOR = void 0;
- var _dom = require("@testing-library/dom");
- var _helpers = require("@testing-library/dom/dist/helpers");
- // isInstanceOfElement can be removed once the peerDependency for @testing-library/dom is bumped to a version that includes https://github.com/testing-library/dom-testing-library/pull/885
- /**
- * Check if an element is of a given type.
- *
- * @param {Element} element The element to test
- * @param {string} elementType Constructor name. E.g. 'HTMLSelectElement'
- */
- function isInstanceOfElement(element, elementType) {
- try {
- const window = (0, _helpers.getWindowFromNode)(element); // Window usually has the element constructors as properties but is not required to do so per specs
- if (typeof window[elementType] === 'function') {
- return element instanceof window[elementType];
- }
- } catch (e) {// The document might not be associated with a window
- } // Fall back to the constructor name as workaround for test environments that
- // a) not associate the document with a window
- // b) not provide the constructor as property of window
- if (/^HTML(\w+)Element$/.test(element.constructor.name)) {
- return element.constructor.name === elementType;
- } // The user passed some node that is not created in a browser-like environment
- throw new Error(`Unable to verify if element is instance of ${elementType}. Please file an issue describing your test environment: https://github.com/testing-library/dom-testing-library/issues/new`);
- }
- function isMousePressEvent(event) {
- return event === 'mousedown' || event === 'mouseup' || event === 'click' || event === 'dblclick';
- }
- function invert(map) {
- const res = {};
- for (const key of Object.keys(map)) {
- res[map[key]] = key;
- }
- return res;
- } // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons
- const BUTTONS_TO_NAMES = {
- 0: 'none',
- 1: 'primary',
- 2: 'secondary',
- 4: 'auxiliary'
- };
- const NAMES_TO_BUTTONS = invert(BUTTONS_TO_NAMES); // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button
- const BUTTON_TO_NAMES = {
- 0: 'primary',
- 1: 'auxiliary',
- 2: 'secondary'
- };
- const NAMES_TO_BUTTON = invert(BUTTON_TO_NAMES);
- function convertMouseButtons(event, init, property, mapping) {
- if (!isMousePressEvent(event)) {
- return 0;
- }
- if (init[property] != null) {
- return init[property];
- }
- if (init.buttons != null) {
- // not sure how to test this. Feel free to try and add a test if you want.
- // istanbul ignore next
- return mapping[BUTTONS_TO_NAMES[init.buttons]] || 0;
- }
- if (init.button != null) {
- // not sure how to test this. Feel free to try and add a test if you want.
- // istanbul ignore next
- return mapping[BUTTON_TO_NAMES[init.button]] || 0;
- }
- return property != 'button' && isMousePressEvent(event) ? 1 : 0;
- }
- function getMouseEventOptions(event, init, clickCount = 0) {
- init = init || {};
- return { ...init,
- // https://developer.mozilla.org/en-US/docs/Web/API/UIEvent/detail
- detail: event === 'mousedown' || event === 'mouseup' || event === 'click' ? 1 + clickCount : clickCount,
- buttons: convertMouseButtons(event, init, 'buttons', NAMES_TO_BUTTONS),
- button: convertMouseButtons(event, init, 'button', NAMES_TO_BUTTON)
- };
- } // Absolutely NO events fire on label elements that contain their control
- // if that control is disabled. NUTS!
- // no joke. There are NO events for: <label><input disabled /><label>
- function isLabelWithInternallyDisabledControl(element) {
- var _element$control;
- return element.tagName === 'LABEL' && ((_element$control = element.control) == null ? void 0 : _element$control.disabled) && element.contains(element.control);
- }
- function getActiveElement(document) {
- const activeElement = document.activeElement;
- if (activeElement != null && activeElement.shadowRoot) {
- return getActiveElement(activeElement.shadowRoot);
- } else {
- return activeElement;
- }
- }
- function supportsMaxLength(element) {
- if (element.tagName === 'TEXTAREA') return true;
- if (element.tagName === 'INPUT') {
- const type = element.getAttribute('type'); // Missing value default is "text"
- if (!type) return true; // https://html.spec.whatwg.org/multipage/input.html#concept-input-apply
- if (type.match(/email|password|search|telephone|text|url/)) return true;
- }
- return false;
- }
- function getSelectionRange(element) {
- if (isContentEditable(element)) {
- const range = element.ownerDocument.getSelection().getRangeAt(0);
- return {
- selectionStart: range.startOffset,
- selectionEnd: range.endOffset
- };
- }
- return {
- selectionStart: element.selectionStart,
- selectionEnd: element.selectionEnd
- };
- } //jsdom is not supporting isContentEditable
- function isContentEditable(element) {
- return element.hasAttribute('contenteditable') && (element.getAttribute('contenteditable') == 'true' || element.getAttribute('contenteditable') == '');
- }
- function getValue(element) {
- if (isContentEditable(element)) {
- return element.textContent;
- }
- return element.value;
- }
- function calculateNewValue(newEntry, element) {
- var _element$getAttribute;
- const {
- selectionStart,
- selectionEnd
- } = getSelectionRange(element);
- const value = getValue(element); // can't use .maxLength property because of a jsdom bug:
- // https://github.com/jsdom/jsdom/issues/2927
- const maxLength = Number((_element$getAttribute = element.getAttribute('maxlength')) != null ? _element$getAttribute : -1);
- let newValue, newSelectionStart;
- if (selectionStart === null) {
- // at the end of an input type that does not support selection ranges
- // https://github.com/testing-library/user-event/issues/316#issuecomment-639744793
- newValue = value + newEntry;
- } else if (selectionStart === selectionEnd) {
- if (selectionStart === 0) {
- // at the beginning of the input
- newValue = newEntry + value;
- } else if (selectionStart === value.length) {
- // at the end of the input
- newValue = value + newEntry;
- } else {
- // in the middle of the input
- newValue = value.slice(0, selectionStart) + newEntry + value.slice(selectionEnd);
- }
- newSelectionStart = selectionStart + newEntry.length;
- } else {
- // we have something selected
- const firstPart = value.slice(0, selectionStart) + newEntry;
- newValue = firstPart + value.slice(selectionEnd);
- newSelectionStart = firstPart.length;
- }
- if (element.type === 'date' && !isValidDateValue(element, newValue)) {
- newValue = value;
- }
- if (element.type === 'time' && !isValidInputTimeValue(element, newValue)) {
- if (isValidInputTimeValue(element, newEntry)) {
- newValue = newEntry;
- } else {
- newValue = value;
- }
- }
- if (!supportsMaxLength(element) || maxLength < 0) {
- return {
- newValue,
- newSelectionStart
- };
- } else {
- return {
- newValue: newValue.slice(0, maxLength),
- newSelectionStart: newSelectionStart > maxLength ? maxLength : newSelectionStart
- };
- }
- }
- function setSelectionRangeIfNecessary(element, newSelectionStart, newSelectionEnd) {
- const {
- selectionStart,
- selectionEnd
- } = getSelectionRange(element);
- if (!isContentEditable(element) && (!element.setSelectionRange || selectionStart === null)) {
- // cannot set selection
- return;
- }
- if (selectionStart !== newSelectionStart || selectionEnd !== newSelectionStart) {
- if (isContentEditable(element)) {
- const range = element.ownerDocument.createRange();
- range.selectNodeContents(element);
- range.setStart(element.firstChild, newSelectionStart);
- range.setEnd(element.firstChild, newSelectionEnd);
- element.ownerDocument.getSelection().removeAllRanges();
- element.ownerDocument.getSelection().addRange(range);
- } else {
- element.setSelectionRange(newSelectionStart, newSelectionEnd);
- }
- }
- }
- const FOCUSABLE_SELECTOR = ['input:not([type=hidden]):not([disabled])', 'button:not([disabled])', 'select:not([disabled])', 'textarea:not([disabled])', '[contenteditable=""]', '[contenteditable="true"]', 'a[href]', '[tabindex]:not([disabled])'].join(', ');
- exports.FOCUSABLE_SELECTOR = FOCUSABLE_SELECTOR;
- function isFocusable(element) {
- return !isLabelWithInternallyDisabledControl(element) && (element == null ? void 0 : element.matches(FOCUSABLE_SELECTOR));
- }
- const CLICKABLE_INPUT_TYPES = ['button', 'color', 'file', 'image', 'reset', 'submit'];
- function isClickableInput(element) {
- return element.tagName === 'BUTTON' || isInstanceOfElement(element, 'HTMLInputElement') && CLICKABLE_INPUT_TYPES.includes(element.type);
- }
- function isVisible(element) {
- const getComputedStyle = (0, _helpers.getWindowFromNode)(element).getComputedStyle;
- for (; element && element.ownerDocument; element = element.parentNode) {
- const display = getComputedStyle(element).display;
- if (display === 'none') {
- return false;
- }
- }
- return true;
- }
- function eventWrapper(cb) {
- let result;
- (0, _dom.getConfig)().eventWrapper(() => {
- result = cb();
- });
- return result;
- }
- function isValidDateValue(element, value) {
- if (element.type !== 'date') return false;
- const clone = element.cloneNode();
- clone.value = value;
- return clone.value === value;
- }
- function buildTimeValue(value) {
- function build(onlyDigitsValue, index) {
- const hours = onlyDigitsValue.slice(0, index);
- const validHours = Math.min(parseInt(hours, 10), 23);
- const minuteCharacters = onlyDigitsValue.slice(index);
- const parsedMinutes = parseInt(minuteCharacters, 10);
- const validMinutes = Math.min(parsedMinutes, 59);
- return `${validHours.toString().padStart(2, '0')}:${validMinutes.toString().padStart(2, '0')}`;
- }
- const onlyDigitsValue = value.replace(/\D/g, '');
- if (onlyDigitsValue.length < 2) {
- return value;
- }
- const firstDigit = parseInt(onlyDigitsValue[0], 10);
- const secondDigit = parseInt(onlyDigitsValue[1], 10);
- if (firstDigit >= 3 || firstDigit === 2 && secondDigit >= 4) {
- let index;
- if (firstDigit >= 3) {
- index = 1;
- } else {
- index = 2;
- }
- return build(onlyDigitsValue, index);
- }
- if (value.length === 2) {
- return value;
- }
- return build(onlyDigitsValue, 2);
- }
- function isValidInputTimeValue(element, timeValue) {
- if (element.type !== 'time') return false;
- const clone = element.cloneNode();
- clone.value = timeValue;
- return clone.value === timeValue;
- }
|