@testing-library/user-event
Version:
Fire events the same way the user does
101 lines (98 loc) • 3.92 kB
JavaScript
import '../utils/click/isClickableInput.js';
import '../utils/dataTransfer/Clipboard.js';
import '../utils/edit/maxLength.js';
import '../utils/edit/isEditable.js';
import '@testing-library/dom';
import '@testing-library/dom/dist/helpers.js';
import '../utils/keyDef/readNextDescriptor.js';
import '../utils/misc/level.js';
import '../options.js';
import '../event/eventMap.js';
import '../event/behavior/click.js';
import '../event/behavior/cut.js';
import '../event/behavior/keydown.js';
import '../event/behavior/keypress.js';
import '../event/behavior/keyup.js';
import '../event/behavior/paste.js';
import { prepareInterceptor } from './interceptor.js';
import { getUIValue } from './value.js';
const UISelection = Symbol('Displayed selection in UI');
function prepareSelectionInterceptor(element) {
prepareInterceptor(element, 'setSelectionRange', function interceptorImpl(start, ...others) {
const isUI = start && typeof start === 'object' && start[UISelection];
if (!isUI) {
this[UISelection] = undefined;
}
return {
applyNative: !!isUI,
realArgs: [
Number(start),
...others
]
};
});
prepareInterceptor(element, 'selectionStart', function interceptorImpl(v) {
this[UISelection] = undefined;
return {
realArgs: v
};
});
prepareInterceptor(element, 'selectionEnd', function interceptorImpl(v) {
this[UISelection] = undefined;
return {
realArgs: v
};
});
prepareInterceptor(element, 'select', function interceptorImpl() {
this[UISelection] = {
anchorOffset: 0,
focusOffset: getUIValue(element).length
};
return {
realArgs: []
};
});
}
function setUISelection(element, { focusOffset: focusOffsetParam , anchorOffset: anchorOffsetParam = focusOffsetParam }, mode = 'replace') {
const valueLength = getUIValue(element).length;
const sanitizeOffset = (o)=>Math.max(0, Math.min(valueLength, o));
const anchorOffset = mode === 'replace' || element[UISelection] === undefined ? sanitizeOffset(anchorOffsetParam) : element[UISelection].anchorOffset;
const focusOffset = sanitizeOffset(focusOffsetParam);
const startOffset = Math.min(anchorOffset, focusOffset);
const endOffset = Math.max(anchorOffset, focusOffset);
element[UISelection] = {
anchorOffset,
focusOffset
};
if (element.selectionStart === startOffset && element.selectionEnd === endOffset) {
return;
}
// eslint-disable-next-line no-new-wrappers
const startObj = new Number(startOffset);
startObj[UISelection] = UISelection;
try {
element.setSelectionRange(startObj, endOffset);
} catch {
// DOMException for invalid state is expected when calling this
// on an element without support for setSelectionRange
}
}
function getUISelection(element) {
var _selectionStart, _selectionEnd, _UISelection;
const sel = (_UISelection = element[UISelection]) !== null && _UISelection !== void 0 ? _UISelection : {
anchorOffset: (_selectionStart = element.selectionStart) !== null && _selectionStart !== void 0 ? _selectionStart : 0,
focusOffset: (_selectionEnd = element.selectionEnd) !== null && _selectionEnd !== void 0 ? _selectionEnd : 0
};
return {
...sel,
startOffset: Math.min(sel.anchorOffset, sel.focusOffset),
endOffset: Math.max(sel.anchorOffset, sel.focusOffset)
};
}
function hasUISelection(element) {
return !!element[UISelection];
}
/** Flag the IDL selection as clean. This does not change the selection. */ function setUISelectionClean(element) {
element[UISelection] = undefined;
}
export { getUISelection, hasUISelection, prepareSelectionInterceptor, setUISelection, setUISelectionClean };