Version 1.0.2 mit node_modules Verzeichnis

This commit is contained in:
ISA
2024-10-02 07:58:24 +02:00
parent f353a06b1b
commit 62b6e55a0a
68228 changed files with 4548477 additions and 651 deletions

20
node_modules/@testing-library/user-event/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2020 Giorgio Polvara
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

124
node_modules/@testing-library/user-event/README.md generated vendored Normal file
View File

@@ -0,0 +1,124 @@
<div align="center">
<h1>user-event</h1>
<a href="https://www.joypixels.com/profiles/emoji/1f415">
<img
height="80"
width="80"
alt="dog"
src="https://raw.githubusercontent.com/testing-library/user-event/main/other/dog.png"
/>
</a>
<p>Fire events the same way the user does</p>
<br />
[**Read The Docs**](https://testing-library.com/docs/user-event/intro)
<br />
</div>
---
<!-- prettier-ignore-start -->
[![Build Status][build-badge]][build]
[![Code Coverage][coverage-badge]][coverage]
[![version][version-badge]][package]
[![downloads][downloads-badge]][npmtrends]
[![MIT License][license-badge]][license]
[![All Contributors][all-contributors-badge]](#contributors)
[![PRs Welcome][prs-badge]][prs]
[![Code of Conduct][coc-badge]][coc]
[![Discord][discord-badge]][discord]
[![Watch on GitHub][github-watch-badge]][github-watch]
[![Star on GitHub][github-star-badge]][github-star]
[![Tweet][twitter-badge]][twitter]
<!-- prettier-ignore-end -->
## The problem
From
[testing-library/dom-testing-library#107](https://github.com/testing-library/dom-testing-library/issues/107):
> [...] it is becoming apparent the need to express user actions on a web page
> using a higher-level abstraction than [`fireEvent`][fire-event]
## The solution
`user-event` tries to simulate the real events that would happen in the browser
as the user interacts with it. For example `userEvent.click(checkbox)` would
change the state of the checkbox.
> [The more your tests resemble the way your software is used, the more
> confidence they can give you.][guiding-principle]
## Issues
Looking to contribute? Look for the [Good First Issue][good-first-issue] label.
### 🐛 Bugs
Please file an issue for bugs, missing documentation, or unexpected behavior.
[**See Bugs**][bugs]
### 💡 Feature Requests
Please file an issue to suggest new features. Vote on feature requests by adding
a 👍. This helps maintainers prioritize what to work on.
[**See Feature Requests**][requests]
### ❓ Questions
For questions related to using the library, please visit a support community
instead of filing an issue on GitHub.
- [Discord][discord]
- [Stack Overflow][stackoverflow]
## Contributors
We most sincerely thank [the people who make this project
possible][contributors]. Contributions of any kind are welcome! 💚
## License
[MIT](LICENSE)
<!-- prettier-ignore-start -->
[npm]: https://www.npmjs.com
[node]: https://nodejs.org
[build-badge]: https://img.shields.io/github/workflow/status/testing-library/user-event/validate/main?logo=github&style=flat-square
[build]: https://github.com/testing-library/user-event/actions?query=workflow%3Avalidate
[coverage-badge]: https://img.shields.io/codecov/c/github/testing-library/user-event.svg?style=flat-square
[coverage]: https://codecov.io/github/testing-library/user-event
[version-badge]: https://img.shields.io/npm/v/@testing-library/user-event.svg?style=flat-square
[package]: https://www.npmjs.com/package/@testing-library/user-event
[downloads-badge]: https://img.shields.io/npm/dm/@testing-library/user-event.svg?style=flat-square
[npmtrends]: http://www.npmtrends.com/@testing-library/user-event
[license-badge]: https://img.shields.io/npm/l/@testing-library/user-event.svg?style=flat-square
[license]: https://github.com/testing-library/user-event/blob/main/LICENSE
[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
[prs]: http://makeapullrequest.com
[coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square
[coc]: https://github.com/testing-library/.github/blob/main/CODE_OF_CONDUCT.md
[github-watch-badge]: https://img.shields.io/github/watchers/testing-library/user-event.svg?style=social
[github-watch]: https://github.com/testing-library/user-event/watchers
[github-star-badge]: https://img.shields.io/github/stars/testing-library/user-event.svg?style=social
[github-star]: https://github.com/testing-library/user-event/stargazers
[twitter]: https://twitter.com/intent/tweet?text=Check%20out%20user-event%20by%20%40@TestingLib%20https%3A%2F%2Fgithub.com%2Ftesting-library%2Fuser-event%20%F0%9F%91%8D
[twitter-badge]: https://img.shields.io/twitter/url/https/github.com/testing-library/user-event.svg?style=social
[all-contributors-badge]: https://img.shields.io/github/all-contributors/testing-library/user-event?color=orange&style=flat-square
[guiding-principle]: https://twitter.com/kentcdodds/status/977018512689455106
[bugs]: https://github.com/testing-library/user-event/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+sort%3Acreated-desc+label%3Abug
[requests]: https://github.com/testing-library/user-event/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3Aenhancement
[good-first-issue]: https://github.com/testing-library/user-event/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3Aenhancement+label%3A%22good+first+issue%22
[fire-event]: https://testing-library.com/docs/dom-testing-library/api-events#fireevent
[discord-badge]: https://img.shields.io/discord/723559267868737556.svg?color=7389D8&labelColor=6A7EC2&logo=discord&logoColor=ffffff&style=flat-square
[discord]: https://discord.gg/testing-library
[stackoverflow]: https://stackoverflow.com/questions/tagged/user-event
[contributors]: https://github.com/testing-library/user-event/blob/main/CONTRIBUTORS.md
<!-- prettier-ignore-end -->

View File

@@ -0,0 +1,28 @@
'use strict';
require('../utils/click/isClickableInput.js');
var Clipboard = require('../utils/dataTransfer/Clipboard.js');
require('../utils/edit/isEditable.js');
require('../utils/edit/maxLength.js');
require('../utils/keyDef/readNextDescriptor.js');
require('../utils/misc/level.js');
require('../options.js');
var copySelection = require('../document/copySelection.js');
async function copy() {
const doc = this.config.document;
var _doc_activeElement;
const target = (_doc_activeElement = doc.activeElement) !== null && _doc_activeElement !== void 0 ? _doc_activeElement : /* istanbul ignore next */ doc.body;
const clipboardData = copySelection.copySelection(target);
if (clipboardData.items.length === 0) {
return;
}
if (this.dispatchUIEvent(target, 'copy', {
clipboardData
}) && this.config.writeToClipboard) {
await Clipboard.writeDataTransferToClipboard(doc, clipboardData);
}
return clipboardData;
}
exports.copy = copy;

View File

@@ -0,0 +1,28 @@
'use strict';
require('../utils/click/isClickableInput.js');
var Clipboard = require('../utils/dataTransfer/Clipboard.js');
require('../utils/edit/isEditable.js');
require('../utils/edit/maxLength.js');
require('../utils/keyDef/readNextDescriptor.js');
require('../utils/misc/level.js');
require('../options.js');
var copySelection = require('../document/copySelection.js');
async function cut() {
const doc = this.config.document;
var _doc_activeElement;
const target = (_doc_activeElement = doc.activeElement) !== null && _doc_activeElement !== void 0 ? _doc_activeElement : /* istanbul ignore next */ doc.body;
const clipboardData = copySelection.copySelection(target);
if (clipboardData.items.length === 0) {
return;
}
if (this.dispatchUIEvent(target, 'cut', {
clipboardData
}) && this.config.writeToClipboard) {
await Clipboard.writeDataTransferToClipboard(target.ownerDocument, clipboardData);
}
return clipboardData;
}
exports.cut = cut;

View File

@@ -0,0 +1,11 @@
'use strict';
var copy = require('./copy.js');
var cut = require('./cut.js');
var paste = require('./paste.js');
exports.copy = copy.copy;
exports.cut = cut.cut;
exports.paste = paste.paste;

View File

@@ -0,0 +1,31 @@
'use strict';
require('../utils/click/isClickableInput.js');
var DataTransfer = require('../utils/dataTransfer/DataTransfer.js');
var Clipboard = require('../utils/dataTransfer/Clipboard.js');
require('../utils/edit/isEditable.js');
require('../utils/edit/maxLength.js');
var getWindow = require('../utils/misc/getWindow.js');
require('../utils/keyDef/readNextDescriptor.js');
require('../utils/misc/level.js');
require('../options.js');
async function paste(clipboardData) {
const doc = this.config.document;
var _doc_activeElement;
const target = (_doc_activeElement = doc.activeElement) !== null && _doc_activeElement !== void 0 ? _doc_activeElement : /* istanbul ignore next */ doc.body;
var _ref;
const dataTransfer = (_ref = typeof clipboardData === 'string' ? getClipboardDataFromString(doc, clipboardData) : clipboardData) !== null && _ref !== void 0 ? _ref : await Clipboard.readDataTransferFromClipboard(doc).catch(()=>{
throw new Error('`userEvent.paste()` without `clipboardData` requires the `ClipboardAPI` to be available.');
});
this.dispatchUIEvent(target, 'paste', {
clipboardData: dataTransfer
});
}
function getClipboardDataFromString(doc, text) {
const dt = DataTransfer.createDataTransfer(getWindow.getWindow(doc));
dt.setData('text', text);
return dt;
}
exports.paste = paste;

View File

@@ -0,0 +1,35 @@
'use strict';
async function click(element) {
const pointerIn = [];
if (!this.config.skipHover) {
pointerIn.push({
target: element
});
}
pointerIn.push({
keys: '[MouseLeft]',
target: element
});
return this.pointer(pointerIn);
}
async function dblClick(element) {
return this.pointer([
{
target: element
},
'[MouseLeft][MouseLeft]'
]);
}
async function tripleClick(element) {
return this.pointer([
{
target: element
},
'[MouseLeft][MouseLeft][MouseLeft]'
]);
}
exports.click = click;
exports.dblClick = dblClick;
exports.tripleClick = tripleClick;

View File

@@ -0,0 +1,24 @@
'use strict';
require('../utils/click/isClickableInput.js');
require('../utils/dataTransfer/Clipboard.js');
require('../utils/edit/isEditable.js');
require('../utils/edit/maxLength.js');
require('../utils/keyDef/readNextDescriptor.js');
require('../utils/misc/level.js');
var cssPointerEvents = require('../utils/pointer/cssPointerEvents.js');
async function hover(element) {
return this.pointer({
target: element
});
}
async function unhover(element) {
cssPointerEvents.assertPointerEvents(this, this.system.pointer.getMouseTarget(this));
return this.pointer({
target: element.ownerDocument.body
});
}
exports.hover = hover;
exports.unhover = unhover;

View File

@@ -0,0 +1,14 @@
'use strict';
var click = require('./click.js');
var hover = require('./hover.js');
var tab = require('./tab.js');
exports.click = click.click;
exports.dblClick = click.dblClick;
exports.tripleClick = click.tripleClick;
exports.hover = hover.hover;
exports.unhover = hover.unhover;
exports.tab = tab.tab;

View File

@@ -0,0 +1,7 @@
'use strict';
async function tab({ shift } = {}) {
return this.keyboard(shift === true ? '{Shift>}{Tab}{/Shift}' : shift === false ? '[/ShiftLeft][/ShiftRight]{Tab}' : '{Tab}');
}
exports.tab = tab;

View File

@@ -0,0 +1,92 @@
'use strict';
const UIValue = Symbol('Displayed value in UI');
const UISelection = Symbol('Displayed selection in UI');
const InitialValue = Symbol('Initial value to compare on blur');
function isUIValue(value) {
return typeof value === 'object' && UIValue in value;
}
function isUISelectionStart(start) {
return !!start && typeof start === 'object' && UISelection in start;
}
function setUIValue(element, value) {
if (element[InitialValue] === undefined) {
element[InitialValue] = element.value;
}
element[UIValue] = value;
// eslint-disable-next-line no-new-wrappers
element.value = Object.assign(new String(value), {
[UIValue]: true
});
}
function getUIValue(element) {
return element[UIValue] === undefined ? element.value : String(element[UIValue]);
}
/** Flag the IDL value as clean. This does not change the value.*/ function setUIValueClean(element) {
element[UIValue] = undefined;
}
function clearInitialValue(element) {
element[InitialValue] = undefined;
}
function getInitialValue(element) {
return element[InitialValue];
}
function setUISelectionRaw(element, selection) {
element[UISelection] = selection;
}
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 = Object.assign(new Number(startOffset), {
[UISelection]: true
});
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 _element_selectionStart, _element_selectionEnd, _element_UISelection;
const sel = (_element_UISelection = element[UISelection]) !== null && _element_UISelection !== void 0 ? _element_UISelection : {
anchorOffset: (_element_selectionStart = element.selectionStart) !== null && _element_selectionStart !== void 0 ? _element_selectionStart : 0,
focusOffset: (_element_selectionEnd = element.selectionEnd) !== null && _element_selectionEnd !== void 0 ? _element_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;
}
exports.clearInitialValue = clearInitialValue;
exports.getInitialValue = getInitialValue;
exports.getUISelection = getUISelection;
exports.getUIValue = getUIValue;
exports.hasUISelection = hasUISelection;
exports.isUISelectionStart = isUISelectionStart;
exports.isUIValue = isUIValue;
exports.setUISelection = setUISelection;
exports.setUISelectionClean = setUISelectionClean;
exports.setUISelectionRaw = setUISelectionRaw;
exports.setUIValue = setUIValue;
exports.setUIValueClean = setUIValueClean;

View File

@@ -0,0 +1,35 @@
'use strict';
require('../utils/click/isClickableInput.js');
var DataTransfer = require('../utils/dataTransfer/DataTransfer.js');
require('../utils/dataTransfer/Clipboard.js');
require('../utils/edit/isEditable.js');
require('../utils/edit/maxLength.js');
var getWindow = require('../utils/misc/getWindow.js');
var selection = require('../utils/focus/selection.js');
require('../utils/keyDef/readNextDescriptor.js');
require('../utils/misc/level.js');
require('../options.js');
var UI = require('./UI.js');
function copySelection(target) {
const data = selection.hasOwnSelection(target) ? {
'text/plain': readSelectedValueFromInput(target)
} : {
'text/plain': String(target.ownerDocument.getSelection())
};
const dt = DataTransfer.createDataTransfer(getWindow.getWindow(target));
for(const type in data){
if (data[type]) {
dt.setData(type, data[type]);
}
}
return dt;
}
function readSelectedValueFromInput(target) {
const sel = UI.getUISelection(target);
const val = UI.getUIValue(target);
return val.substring(sel.startOffset, sel.endOffset);
}
exports.copySelection = copySelection;

View File

@@ -0,0 +1,24 @@
'use strict';
require('../utils/click/isClickableInput.js');
require('../utils/dataTransfer/Clipboard.js');
var isContentEditable = require('../utils/edit/isContentEditable.js');
require('../utils/edit/isEditable.js');
require('../utils/edit/maxLength.js');
require('../utils/keyDef/readNextDescriptor.js');
require('../utils/misc/level.js');
require('../options.js');
var UI = require('./UI.js');
function getValueOrTextContent(element) {
// istanbul ignore if
if (!element) {
return null;
}
if (isContentEditable.isContentEditable(element)) {
return element.textContent;
}
return UI.getUIValue(element);
}
exports.getValueOrTextContent = getValueOrTextContent;

View File

@@ -0,0 +1,17 @@
'use strict';
var UI = require('./UI.js');
var getValueOrTextContent = require('./getValueOrTextContent.js');
var copySelection = require('./copySelection.js');
var trackValue = require('./trackValue.js');
exports.clearInitialValue = UI.clearInitialValue;
exports.getUISelection = UI.getUISelection;
exports.getUIValue = UI.getUIValue;
exports.setUISelection = UI.setUISelection;
exports.setUIValue = UI.setUIValue;
exports.getValueOrTextContent = getValueOrTextContent.getValueOrTextContent;
exports.copySelection = copySelection.copySelection;
exports.commitValueAfterInput = trackValue.commitValueAfterInput;

View File

@@ -0,0 +1,110 @@
'use strict';
require('../utils/click/isClickableInput.js');
require('../utils/dataTransfer/Clipboard.js');
require('../utils/edit/isEditable.js');
require('../utils/edit/maxLength.js');
var isElementType = require('../utils/misc/isElementType.js');
require('../utils/keyDef/readNextDescriptor.js');
require('../utils/misc/level.js');
require('../options.js');
var trackValue = require('./trackValue.js');
var UI = require('./UI.js');
const Interceptor = Symbol('Interceptor for programmatical calls');
function prepareInterceptor(element, propName, interceptorImpl) {
const prototypeDescriptor = Object.getOwnPropertyDescriptor(element.constructor.prototype, propName);
const objectDescriptor = Object.getOwnPropertyDescriptor(element, propName);
const target = (prototypeDescriptor === null || prototypeDescriptor === void 0 ? void 0 : prototypeDescriptor.set) ? 'set' : 'value';
/* istanbul ignore if */ if (typeof (prototypeDescriptor === null || prototypeDescriptor === void 0 ? void 0 : prototypeDescriptor[target]) !== 'function' || prototypeDescriptor[target][Interceptor]) {
throw new Error(`Element ${element.tagName} does not implement "${String(propName)}".`);
}
function intercept(...args) {
const { applyNative = false, realArgs, then } = interceptorImpl.call(this, ...args);
const realFunc = (!applyNative && objectDescriptor || prototypeDescriptor)[target];
if (target === 'set') {
realFunc.call(this, realArgs);
} else {
realFunc.call(this, ...realArgs);
}
then === null || then === void 0 ? void 0 : then();
}
intercept[Interceptor] = Interceptor;
Object.defineProperty(element, propName, {
...objectDescriptor !== null && objectDescriptor !== void 0 ? objectDescriptor : prototypeDescriptor,
[target]: intercept
});
}
function prepareValueInterceptor(element) {
prepareInterceptor(element, 'value', function interceptorImpl(v) {
const isUI = UI.isUIValue(v);
if (isUI) {
trackValue.startTrackValue(this);
}
return {
applyNative: !!isUI,
realArgs: sanitizeValue(this, v),
then: isUI ? undefined : ()=>trackValue.trackOrSetValue(this, String(v))
};
});
}
function sanitizeValue(element, v) {
// Workaround for JSDOM
if (isElementType.isElementType(element, 'input', {
type: 'number'
}) && String(v) !== '' && !Number.isNaN(Number(v))) {
// Setting value to "1." results in `null` in JSDOM
return String(Number(v));
}
return String(v);
}
function prepareSelectionInterceptor(element) {
prepareInterceptor(element, 'setSelectionRange', function interceptorImpl(start, ...others) {
const isUI = UI.isUISelectionStart(start);
return {
applyNative: !!isUI,
realArgs: [
Number(start),
...others
],
then: ()=>isUI ? undefined : UI.setUISelectionClean(element)
};
});
prepareInterceptor(element, 'selectionStart', function interceptorImpl(v) {
return {
realArgs: v,
then: ()=>UI.setUISelectionClean(element)
};
});
prepareInterceptor(element, 'selectionEnd', function interceptorImpl(v) {
return {
realArgs: v,
then: ()=>UI.setUISelectionClean(element)
};
});
prepareInterceptor(element, 'select', function interceptorImpl() {
return {
realArgs: [],
then: ()=>UI.setUISelectionRaw(element, {
anchorOffset: 0,
focusOffset: UI.getUIValue(element).length
})
};
});
}
function prepareRangeTextInterceptor(element) {
prepareInterceptor(element, 'setRangeText', function interceptorImpl(...realArgs) {
return {
realArgs,
then: ()=>{
UI.setUIValueClean(element);
UI.setUISelectionClean(element);
}
};
});
}
exports.prepareInterceptor = prepareInterceptor;
exports.prepareRangeTextInterceptor = prepareRangeTextInterceptor;
exports.prepareSelectionInterceptor = prepareSelectionInterceptor;
exports.prepareValueInterceptor = prepareValueInterceptor;

View File

@@ -0,0 +1,64 @@
'use strict';
var dispatchEvent = require('../event/dispatchEvent.js');
require('../utils/click/isClickableInput.js');
require('../utils/dataTransfer/Clipboard.js');
require('../utils/edit/isEditable.js');
require('../utils/edit/maxLength.js');
var isElementType = require('../utils/misc/isElementType.js');
require('../utils/keyDef/readNextDescriptor.js');
require('../utils/misc/level.js');
require('../options.js');
var UI = require('./UI.js');
require('@testing-library/dom');
var interceptor = require('./interceptor.js');
const isPrepared = Symbol('Node prepared with document state workarounds');
function prepareDocument(document) {
if (document[isPrepared]) {
return;
}
document.addEventListener('focus', (e)=>{
const el = e.target;
prepareElement(el);
}, {
capture: true,
passive: true
});
// Our test environment defaults to `document.body` as `activeElement`.
// In other environments this might be `null` when preparing.
// istanbul ignore else
if (document.activeElement) {
prepareElement(document.activeElement);
}
document.addEventListener('blur', (e)=>{
const el = e.target;
const initialValue = UI.getInitialValue(el);
if (initialValue !== undefined) {
if (el.value !== initialValue) {
dispatchEvent.dispatchDOMEvent(el, 'change');
}
UI.clearInitialValue(el);
}
}, {
capture: true,
passive: true
});
document[isPrepared] = isPrepared;
}
function prepareElement(el) {
if (el[isPrepared]) {
return;
}
if (isElementType.isElementType(el, [
'input',
'textarea'
])) {
interceptor.prepareValueInterceptor(el);
interceptor.prepareSelectionInterceptor(el);
interceptor.prepareRangeTextInterceptor(el);
}
el[isPrepared] = isPrepared;
}
exports.prepareDocument = prepareDocument;

View File

@@ -0,0 +1,63 @@
'use strict';
require('../utils/click/isClickableInput.js');
require('../utils/dataTransfer/Clipboard.js');
require('../utils/edit/isEditable.js');
require('../utils/edit/maxLength.js');
var getWindow = require('../utils/misc/getWindow.js');
require('../utils/keyDef/readNextDescriptor.js');
require('../utils/misc/level.js');
require('../options.js');
var UI = require('./UI.js');
const TrackChanges = Symbol('Track programmatic changes for React workaround');
// When the input event happens in the browser, React executes all event handlers
// and if they change state of a controlled value, nothing happens.
// But when we trigger the event handlers in test environment with React@17,
// the changes are rolled back before the state update is applied.
// This results in a reset cursor.
// There might be a better way to work around if we figure out
// why the batched update is executed differently in our test environment.
function isReact17Element(element) {
return Object.getOwnPropertyNames(element).some((k)=>k.startsWith('__react')) && getWindow.getWindow(element).REACT_VERSION === 17;
}
function startTrackValue(element) {
if (!isReact17Element(element)) {
return;
}
element[TrackChanges] = {
previousValue: String(element.value),
tracked: []
};
}
function trackOrSetValue(element, v) {
var _element_TrackChanges_tracked, _element_TrackChanges;
(_element_TrackChanges = element[TrackChanges]) === null || _element_TrackChanges === void 0 ? void 0 : (_element_TrackChanges_tracked = _element_TrackChanges.tracked) === null || _element_TrackChanges_tracked === void 0 ? void 0 : _element_TrackChanges_tracked.push(v);
if (!element[TrackChanges]) {
UI.setUIValueClean(element);
UI.setUISelection(element, {
focusOffset: v.length
});
}
}
function commitValueAfterInput(element, cursorOffset) {
var _changes_tracked;
const changes = element[TrackChanges];
element[TrackChanges] = undefined;
if (!(changes === null || changes === void 0 ? void 0 : (_changes_tracked = changes.tracked) === null || _changes_tracked === void 0 ? void 0 : _changes_tracked.length)) {
return;
}
const isJustReactStateUpdate = changes.tracked.length === 2 && changes.tracked[0] === changes.previousValue && changes.tracked[1] === element.value;
if (!isJustReactStateUpdate) {
UI.setUIValueClean(element);
}
if (UI.hasUISelection(element)) {
UI.setUISelection(element, {
focusOffset: isJustReactStateUpdate ? cursorOffset : element.value.length
});
}
}
exports.commitValueAfterInput = commitValueAfterInput;
exports.startTrackValue = startTrackValue;
exports.trackOrSetValue = trackOrSetValue;

View File

@@ -0,0 +1,38 @@
'use strict';
require('../../utils/click/isClickableInput.js');
require('../../utils/dataTransfer/Clipboard.js');
require('../../utils/edit/isEditable.js');
require('../../utils/edit/maxLength.js');
var isElementType = require('../../utils/misc/isElementType.js');
var getWindow = require('../../utils/misc/getWindow.js');
var isFocusable = require('../../utils/focus/isFocusable.js');
require('../../utils/keyDef/readNextDescriptor.js');
var cloneEvent = require('../../utils/misc/cloneEvent.js');
require('../../utils/misc/level.js');
require('../../options.js');
var focus = require('../focus.js');
var registry = require('./registry.js');
registry.behavior.click = (event, target, instance)=>{
const context = target.closest('button,input,label,select,textarea');
const control = context && isElementType.isElementType(context, 'label') && context.control;
if (control) {
return ()=>{
if (isFocusable.isFocusable(control)) {
focus.focusElement(control);
}
instance.dispatchEvent(control, cloneEvent.cloneEvent(event));
};
} else if (isElementType.isElementType(target, 'input', {
type: 'file'
})) {
return ()=>{
// blur fires when the file selector pops up
focus.blurElement(target);
target.dispatchEvent(new (getWindow.getWindow(target)).Event('fileDialog'));
// focus fires after the file selector has been closed
focus.focusElement(target);
};
}
};

View File

@@ -0,0 +1,19 @@
'use strict';
require('../../utils/click/isClickableInput.js');
require('../../utils/dataTransfer/Clipboard.js');
var isEditable = require('../../utils/edit/isEditable.js');
require('../../utils/edit/maxLength.js');
require('../../utils/keyDef/readNextDescriptor.js');
require('../../utils/misc/level.js');
require('../../options.js');
var input = require('../input.js');
var registry = require('./registry.js');
registry.behavior.cut = (event, target, instance)=>{
return ()=>{
if (isEditable.isEditable(target)) {
input.input(instance, target, '', 'deleteByCut');
}
};
};

View File

@@ -0,0 +1,13 @@
'use strict';
require('./click.js');
require('./cut.js');
require('./keydown.js');
require('./keypress.js');
require('./keyup.js');
require('./paste.js');
var registry = require('./registry.js');
exports.behavior = registry.behavior;

View File

@@ -0,0 +1,133 @@
'use strict';
var UI = require('../../document/UI.js');
var getValueOrTextContent = require('../../document/getValueOrTextContent.js');
require('../../utils/click/isClickableInput.js');
require('../../utils/dataTransfer/Clipboard.js');
var isContentEditable = require('../../utils/edit/isContentEditable.js');
var isEditable = require('../../utils/edit/isEditable.js');
require('../../utils/edit/maxLength.js');
var isElementType = require('../../utils/misc/isElementType.js');
var getTabDestination = require('../../utils/focus/getTabDestination.js');
var selection = require('../../utils/focus/selection.js');
require('../../utils/keyDef/readNextDescriptor.js');
require('../../utils/misc/level.js');
require('../../options.js');
var focus = require('../focus.js');
var input = require('../input.js');
var moveSelection = require('../selection/moveSelection.js');
var selectAll = require('../selection/selectAll.js');
var setSelectionRange = require('../selection/setSelectionRange.js');
var radio = require('../radio.js');
var registry = require('./registry.js');
registry.behavior.keydown = (event, target, instance)=>{
var _keydownBehavior_event_key;
var _keydownBehavior_event_key1;
return (_keydownBehavior_event_key1 = (_keydownBehavior_event_key = keydownBehavior[event.key]) === null || _keydownBehavior_event_key === void 0 ? void 0 : _keydownBehavior_event_key.call(keydownBehavior, event, target, instance)) !== null && _keydownBehavior_event_key1 !== void 0 ? _keydownBehavior_event_key1 : combinationBehavior(event, target, instance);
};
const keydownBehavior = {
ArrowDown: (event, target, instance)=>{
/* istanbul ignore else */ if (isElementType.isElementType(target, 'input', {
type: 'radio'
})) {
return ()=>radio.walkRadio(instance, target, -1);
}
},
ArrowLeft: (event, target, instance)=>{
if (isElementType.isElementType(target, 'input', {
type: 'radio'
})) {
return ()=>radio.walkRadio(instance, target, -1);
}
return ()=>moveSelection.moveSelection(target, -1);
},
ArrowRight: (event, target, instance)=>{
if (isElementType.isElementType(target, 'input', {
type: 'radio'
})) {
return ()=>radio.walkRadio(instance, target, 1);
}
return ()=>moveSelection.moveSelection(target, 1);
},
ArrowUp: (event, target, instance)=>{
/* istanbul ignore else */ if (isElementType.isElementType(target, 'input', {
type: 'radio'
})) {
return ()=>radio.walkRadio(instance, target, 1);
}
},
Backspace: (event, target, instance)=>{
if (isEditable.isEditable(target)) {
return ()=>{
input.input(instance, target, '', 'deleteContentBackward');
};
}
},
Delete: (event, target, instance)=>{
if (isEditable.isEditable(target)) {
return ()=>{
input.input(instance, target, '', 'deleteContentForward');
};
}
},
End: (event, target)=>{
if (isElementType.isElementType(target, [
'input',
'textarea'
]) || isContentEditable.isContentEditable(target)) {
return ()=>{
var _getValueOrTextContent;
var _getValueOrTextContent_length;
const newPos = (_getValueOrTextContent_length = (_getValueOrTextContent = getValueOrTextContent.getValueOrTextContent(target)) === null || _getValueOrTextContent === void 0 ? void 0 : _getValueOrTextContent.length) !== null && _getValueOrTextContent_length !== void 0 ? _getValueOrTextContent_length : /* istanbul ignore next */ 0;
setSelectionRange.setSelectionRange(target, newPos, newPos);
};
}
},
Home: (event, target)=>{
if (isElementType.isElementType(target, [
'input',
'textarea'
]) || isContentEditable.isContentEditable(target)) {
return ()=>{
setSelectionRange.setSelectionRange(target, 0, 0);
};
}
},
PageDown: (event, target)=>{
if (isElementType.isElementType(target, [
'input'
])) {
return ()=>{
const newPos = UI.getUIValue(target).length;
setSelectionRange.setSelectionRange(target, newPos, newPos);
};
}
},
PageUp: (event, target)=>{
if (isElementType.isElementType(target, [
'input'
])) {
return ()=>{
setSelectionRange.setSelectionRange(target, 0, 0);
};
}
},
Tab: (event, target, instance)=>{
return ()=>{
const dest = getTabDestination.getTabDestination(target, instance.system.keyboard.modifiers.Shift);
focus.focusElement(dest);
if (selection.hasOwnSelection(dest)) {
UI.setUISelection(dest, {
anchorOffset: 0,
focusOffset: dest.value.length
});
}
};
}
};
const combinationBehavior = (event, target, instance)=>{
if (event.code === 'KeyA' && instance.system.keyboard.modifiers.Control) {
return ()=>selectAll.selectAll(target);
}
};

View File

@@ -0,0 +1,56 @@
'use strict';
require('../../utils/click/isClickableInput.js');
require('../../utils/dataTransfer/Clipboard.js');
var isContentEditable = require('../../utils/edit/isContentEditable.js');
var isEditable = require('../../utils/edit/isEditable.js');
require('../../utils/edit/maxLength.js');
var isElementType = require('../../utils/misc/isElementType.js');
require('../../utils/keyDef/readNextDescriptor.js');
require('../../utils/misc/level.js');
require('../../options.js');
var input = require('../input.js');
var registry = require('./registry.js');
registry.behavior.keypress = (event, target, instance)=>{
if (event.key === 'Enter') {
if (isElementType.isElementType(target, 'button') || isElementType.isElementType(target, 'input') && ClickInputOnEnter.includes(target.type) || isElementType.isElementType(target, 'a') && Boolean(target.href)) {
return ()=>{
instance.dispatchUIEvent(target, 'click');
};
} else if (isElementType.isElementType(target, 'input')) {
const form = target.form;
const submit = form === null || form === void 0 ? void 0 : form.querySelector('input[type="submit"], button:not([type]), button[type="submit"]');
if (submit) {
return ()=>instance.dispatchUIEvent(submit, 'click');
} else if (form && SubmitSingleInputOnEnter.includes(target.type) && form.querySelectorAll('input').length === 1) {
return ()=>instance.dispatchUIEvent(form, 'submit');
} else {
return;
}
}
}
if (isEditable.isEditable(target)) {
const inputType = event.key === 'Enter' ? isContentEditable.isContentEditable(target) && !instance.system.keyboard.modifiers.Shift ? 'insertParagraph' : 'insertLineBreak' : 'insertText';
const inputData = event.key === 'Enter' ? '\n' : event.key;
return ()=>input.input(instance, target, inputData, inputType);
}
};
const ClickInputOnEnter = [
'button',
'color',
'file',
'image',
'reset',
'submit'
];
const SubmitSingleInputOnEnter = [
'email',
'month',
'password',
'search',
'tel',
'text',
'url',
'week'
];

View File

@@ -0,0 +1,22 @@
'use strict';
var isClickableInput = require('../../utils/click/isClickableInput.js');
require('../../utils/dataTransfer/Clipboard.js');
require('../../utils/edit/isEditable.js');
require('../../utils/edit/maxLength.js');
require('../../utils/keyDef/readNextDescriptor.js');
require('../../utils/misc/level.js');
require('../../options.js');
var registry = require('./registry.js');
registry.behavior.keyup = (event, target, instance)=>{
var _keyupBehavior_event_key;
return (_keyupBehavior_event_key = keyupBehavior[event.key]) === null || _keyupBehavior_event_key === void 0 ? void 0 : _keyupBehavior_event_key.call(keyupBehavior, event, target, instance);
};
const keyupBehavior = {
' ': (event, target, instance)=>{
if (isClickableInput.isClickableInput(target)) {
return ()=>instance.dispatchUIEvent(target, 'click');
}
}
};

View File

@@ -0,0 +1,23 @@
'use strict';
require('../../utils/click/isClickableInput.js');
require('../../utils/dataTransfer/Clipboard.js');
var isEditable = require('../../utils/edit/isEditable.js');
require('../../utils/edit/maxLength.js');
require('../../utils/keyDef/readNextDescriptor.js');
require('../../utils/misc/level.js');
require('../../options.js');
var input = require('../input.js');
var registry = require('./registry.js');
registry.behavior.paste = (event, target, instance)=>{
if (isEditable.isEditable(target)) {
return ()=>{
var _event_clipboardData;
const insertData = (_event_clipboardData = event.clipboardData) === null || _event_clipboardData === void 0 ? void 0 : _event_clipboardData.getData('text');
if (insertData) {
input.input(instance, target, insertData, 'insertFromPaste');
}
};
}
};

View File

@@ -0,0 +1,5 @@
'use strict';
const behavior = {};
exports.behavior = behavior;

View File

@@ -0,0 +1,200 @@
'use strict';
require('../utils/click/isClickableInput.js');
require('../utils/dataTransfer/Clipboard.js');
require('../utils/edit/isEditable.js');
require('../utils/edit/maxLength.js');
var getWindow = require('../utils/misc/getWindow.js');
require('../utils/keyDef/readNextDescriptor.js');
require('../utils/misc/level.js');
require('../options.js');
var eventMap = require('./eventMap.js');
const eventInitializer = {
ClipboardEvent: [
initClipboardEvent
],
Event: [],
InputEvent: [
initUIEvent,
initInputEvent
],
MouseEvent: [
initUIEvent,
initUIEventModififiers,
initMouseEvent
],
PointerEvent: [
initUIEvent,
initUIEventModififiers,
initMouseEvent,
initPointerEvent
],
KeyboardEvent: [
initUIEvent,
initUIEventModififiers,
initKeyboardEvent
]
};
function createEvent(type, target, init) {
const window = getWindow.getWindow(target);
const { EventType, defaultInit } = eventMap.eventMap[type];
const event = new (getEventConstructors(window))[EventType](type, defaultInit);
eventInitializer[EventType].forEach((f)=>f(event, init !== null && init !== void 0 ? init : {}));
return event;
}
/* istanbul ignore next */ function getEventConstructors(window) {
var _window_Event;
/* eslint-disable @typescript-eslint/no-unnecessary-condition, @typescript-eslint/no-extraneous-class */ const Event = (_window_Event = window.Event) !== null && _window_Event !== void 0 ? _window_Event : class Event {
};
var _window_AnimationEvent;
const AnimationEvent = (_window_AnimationEvent = window.AnimationEvent) !== null && _window_AnimationEvent !== void 0 ? _window_AnimationEvent : class AnimationEvent extends Event {
};
var _window_ClipboardEvent;
const ClipboardEvent = (_window_ClipboardEvent = window.ClipboardEvent) !== null && _window_ClipboardEvent !== void 0 ? _window_ClipboardEvent : class ClipboardEvent extends Event {
};
var _window_PopStateEvent;
const PopStateEvent = (_window_PopStateEvent = window.PopStateEvent) !== null && _window_PopStateEvent !== void 0 ? _window_PopStateEvent : class PopStateEvent extends Event {
};
var _window_ProgressEvent;
const ProgressEvent = (_window_ProgressEvent = window.ProgressEvent) !== null && _window_ProgressEvent !== void 0 ? _window_ProgressEvent : class ProgressEvent extends Event {
};
var _window_TransitionEvent;
const TransitionEvent = (_window_TransitionEvent = window.TransitionEvent) !== null && _window_TransitionEvent !== void 0 ? _window_TransitionEvent : class TransitionEvent extends Event {
};
var _window_UIEvent;
const UIEvent = (_window_UIEvent = window.UIEvent) !== null && _window_UIEvent !== void 0 ? _window_UIEvent : class UIEvent extends Event {
};
var _window_CompositionEvent;
const CompositionEvent = (_window_CompositionEvent = window.CompositionEvent) !== null && _window_CompositionEvent !== void 0 ? _window_CompositionEvent : class CompositionEvent extends UIEvent {
};
var _window_FocusEvent;
const FocusEvent = (_window_FocusEvent = window.FocusEvent) !== null && _window_FocusEvent !== void 0 ? _window_FocusEvent : class FocusEvent extends UIEvent {
};
var _window_InputEvent;
const InputEvent = (_window_InputEvent = window.InputEvent) !== null && _window_InputEvent !== void 0 ? _window_InputEvent : class InputEvent extends UIEvent {
};
var _window_KeyboardEvent;
const KeyboardEvent = (_window_KeyboardEvent = window.KeyboardEvent) !== null && _window_KeyboardEvent !== void 0 ? _window_KeyboardEvent : class KeyboardEvent extends UIEvent {
};
var _window_MouseEvent;
const MouseEvent = (_window_MouseEvent = window.MouseEvent) !== null && _window_MouseEvent !== void 0 ? _window_MouseEvent : class MouseEvent extends UIEvent {
};
var _window_DragEvent;
const DragEvent = (_window_DragEvent = window.DragEvent) !== null && _window_DragEvent !== void 0 ? _window_DragEvent : class DragEvent extends MouseEvent {
};
var _window_PointerEvent;
const PointerEvent = (_window_PointerEvent = window.PointerEvent) !== null && _window_PointerEvent !== void 0 ? _window_PointerEvent : class PointerEvent extends MouseEvent {
};
var _window_TouchEvent;
const TouchEvent = (_window_TouchEvent = window.TouchEvent) !== null && _window_TouchEvent !== void 0 ? _window_TouchEvent : class TouchEvent extends UIEvent {
};
/* eslint-enable @typescript-eslint/no-unnecessary-condition, @typescript-eslint/no-extraneous-class */ return {
Event,
AnimationEvent,
ClipboardEvent,
PopStateEvent,
ProgressEvent,
TransitionEvent,
UIEvent,
CompositionEvent,
FocusEvent,
InputEvent,
KeyboardEvent,
MouseEvent,
DragEvent,
PointerEvent,
TouchEvent
};
}
function assignProps(obj, props) {
for (const [key, value] of Object.entries(props)){
Object.defineProperty(obj, key, {
get: ()=>value !== null && value !== void 0 ? value : null
});
}
}
function sanitizeNumber(n) {
return Number(n !== null && n !== void 0 ? n : 0);
}
function initClipboardEvent(event, { clipboardData }) {
assignProps(event, {
clipboardData
});
}
function initInputEvent(event, { data, inputType, isComposing }) {
assignProps(event, {
data,
isComposing: Boolean(isComposing),
inputType: String(inputType)
});
}
function initUIEvent(event, { view, detail }) {
assignProps(event, {
view,
detail: sanitizeNumber(detail !== null && detail !== void 0 ? detail : 0)
});
}
function initUIEventModififiers(event, { altKey, ctrlKey, metaKey, shiftKey, modifierAltGraph, modifierCapsLock, modifierFn, modifierFnLock, modifierNumLock, modifierScrollLock, modifierSymbol, modifierSymbolLock }) {
assignProps(event, {
altKey: Boolean(altKey),
ctrlKey: Boolean(ctrlKey),
metaKey: Boolean(metaKey),
shiftKey: Boolean(shiftKey),
getModifierState (k) {
return Boolean({
Alt: altKey,
AltGraph: modifierAltGraph,
CapsLock: modifierCapsLock,
Control: ctrlKey,
Fn: modifierFn,
FnLock: modifierFnLock,
Meta: metaKey,
NumLock: modifierNumLock,
ScrollLock: modifierScrollLock,
Shift: shiftKey,
Symbol: modifierSymbol,
SymbolLock: modifierSymbolLock
}[k]);
}
});
}
function initKeyboardEvent(event, { key, code, location, repeat, isComposing, charCode }) {
assignProps(event, {
key: String(key),
code: String(code),
location: sanitizeNumber(location),
repeat: Boolean(repeat),
isComposing: Boolean(isComposing),
charCode
});
}
function initMouseEvent(event, { x, y, screenX, screenY, clientX = x, clientY = y, button, buttons, relatedTarget }) {
assignProps(event, {
screenX: sanitizeNumber(screenX),
screenY: sanitizeNumber(screenY),
clientX: sanitizeNumber(clientX),
x: sanitizeNumber(clientX),
clientY: sanitizeNumber(clientY),
y: sanitizeNumber(clientY),
button: sanitizeNumber(button),
buttons: sanitizeNumber(buttons),
relatedTarget
});
}
function initPointerEvent(event, { pointerId, width, height, pressure, tangentialPressure, tiltX, tiltY, twist, pointerType, isPrimary }) {
assignProps(event, {
pointerId: sanitizeNumber(pointerId),
width: sanitizeNumber(width),
height: sanitizeNumber(height),
pressure: sanitizeNumber(pressure),
tangentialPressure: sanitizeNumber(tangentialPressure),
tiltX: sanitizeNumber(tiltX),
tiltY: sanitizeNumber(tiltY),
twist: sanitizeNumber(twist),
pointerType: String(pointerType),
isPrimary: Boolean(isPrimary)
});
}
exports.createEvent = createEvent;

View File

@@ -0,0 +1,54 @@
'use strict';
require('./behavior/click.js');
require('./behavior/cut.js');
require('./behavior/keydown.js');
require('./behavior/keypress.js');
require('./behavior/keyup.js');
require('./behavior/paste.js');
var registry = require('./behavior/registry.js');
var wrapEvent = require('./wrapEvent.js');
var eventMap = require('./eventMap.js');
var createEvent = require('./createEvent.js');
function dispatchUIEvent(target, type, init, preventDefault = false) {
if (eventMap.isMouseEvent(type) || eventMap.isKeyboardEvent(type)) {
init = {
...init,
...this.system.getUIEventModifiers()
};
}
const event = createEvent.createEvent(type, target, init);
return dispatchEvent.call(this, target, event, preventDefault);
}
function dispatchEvent(target, event, preventDefault = false) {
var _behavior_type;
const type = event.type;
const behaviorImplementation = preventDefault ? ()=>{} : (_behavior_type = registry.behavior[type]) === null || _behavior_type === void 0 ? void 0 : _behavior_type.call(registry.behavior, event, target, this);
if (behaviorImplementation) {
event.preventDefault();
let defaultPrevented = false;
Object.defineProperty(event, 'defaultPrevented', {
get: ()=>defaultPrevented
});
Object.defineProperty(event, 'preventDefault', {
value: ()=>{
defaultPrevented = event.cancelable;
}
});
wrapEvent.wrapEvent(()=>target.dispatchEvent(event));
if (!defaultPrevented) {
behaviorImplementation();
}
return !defaultPrevented;
}
return wrapEvent.wrapEvent(()=>target.dispatchEvent(event));
}
function dispatchDOMEvent(target, type, init) {
const event = createEvent.createEvent(type, target, init);
wrapEvent.wrapEvent(()=>target.dispatchEvent(event));
}
exports.dispatchDOMEvent = dispatchDOMEvent;
exports.dispatchEvent = dispatchEvent;
exports.dispatchUIEvent = dispatchUIEvent;

View File

@@ -0,0 +1,249 @@
'use strict';
const eventMap = {
auxclick: {
EventType: 'PointerEvent',
defaultInit: {
bubbles: true,
cancelable: true,
composed: true
}
},
beforeinput: {
EventType: 'InputEvent',
defaultInit: {
bubbles: true,
cancelable: true,
composed: true
}
},
click: {
EventType: 'PointerEvent',
defaultInit: {
bubbles: true,
cancelable: true,
composed: true
}
},
contextmenu: {
EventType: 'PointerEvent',
defaultInit: {
bubbles: true,
cancelable: true,
composed: true
}
},
copy: {
EventType: 'ClipboardEvent',
defaultInit: {
bubbles: true,
cancelable: true,
composed: true
}
},
change: {
EventType: 'Event',
defaultInit: {
bubbles: true,
cancelable: false
}
},
cut: {
EventType: 'ClipboardEvent',
defaultInit: {
bubbles: true,
cancelable: true,
composed: true
}
},
dblclick: {
EventType: 'MouseEvent',
defaultInit: {
bubbles: true,
cancelable: true,
composed: true
}
},
keydown: {
EventType: 'KeyboardEvent',
defaultInit: {
bubbles: true,
cancelable: true,
composed: true
}
},
keypress: {
EventType: 'KeyboardEvent',
defaultInit: {
bubbles: true,
cancelable: true,
composed: true
}
},
keyup: {
EventType: 'KeyboardEvent',
defaultInit: {
bubbles: true,
cancelable: true,
composed: true
}
},
paste: {
EventType: 'ClipboardEvent',
defaultInit: {
bubbles: true,
cancelable: true,
composed: true
}
},
input: {
EventType: 'InputEvent',
defaultInit: {
bubbles: true,
cancelable: false,
composed: true
}
},
mousedown: {
EventType: 'MouseEvent',
defaultInit: {
bubbles: true,
cancelable: true,
composed: true
}
},
mouseenter: {
EventType: 'MouseEvent',
defaultInit: {
bubbles: false,
cancelable: false,
composed: true
}
},
mouseleave: {
EventType: 'MouseEvent',
defaultInit: {
bubbles: false,
cancelable: false,
composed: true
}
},
mousemove: {
EventType: 'MouseEvent',
defaultInit: {
bubbles: true,
cancelable: true,
composed: true
}
},
mouseout: {
EventType: 'MouseEvent',
defaultInit: {
bubbles: true,
cancelable: true,
composed: true
}
},
mouseover: {
EventType: 'MouseEvent',
defaultInit: {
bubbles: true,
cancelable: true,
composed: true
}
},
mouseup: {
EventType: 'MouseEvent',
defaultInit: {
bubbles: true,
cancelable: true,
composed: true
}
},
pointerover: {
EventType: 'PointerEvent',
defaultInit: {
bubbles: true,
cancelable: true,
composed: true
}
},
pointerenter: {
EventType: 'PointerEvent',
defaultInit: {
bubbles: false,
cancelable: false
}
},
pointerdown: {
EventType: 'PointerEvent',
defaultInit: {
bubbles: true,
cancelable: true,
composed: true
}
},
pointermove: {
EventType: 'PointerEvent',
defaultInit: {
bubbles: true,
cancelable: true,
composed: true
}
},
pointerup: {
EventType: 'PointerEvent',
defaultInit: {
bubbles: true,
cancelable: true,
composed: true
}
},
pointercancel: {
EventType: 'PointerEvent',
defaultInit: {
bubbles: true,
cancelable: false,
composed: true
}
},
pointerout: {
EventType: 'PointerEvent',
defaultInit: {
bubbles: true,
cancelable: true,
composed: true
}
},
pointerleave: {
EventType: 'PointerEvent',
defaultInit: {
bubbles: false,
cancelable: false
}
},
submit: {
EventType: 'Event',
defaultInit: {
bubbles: true,
cancelable: true
}
}
};
function getEventClass(type) {
return eventMap[type].EventType;
}
const mouseEvents = [
'MouseEvent',
'PointerEvent'
];
function isMouseEvent(type) {
return mouseEvents.includes(getEventClass(type));
}
function isKeyboardEvent(type) {
return getEventClass(type) === 'KeyboardEvent';
}
exports.eventMap = eventMap;
exports.isKeyboardEvent = isKeyboardEvent;
exports.isMouseEvent = isMouseEvent;

View File

@@ -0,0 +1,38 @@
'use strict';
require('../utils/click/isClickableInput.js');
require('../utils/dataTransfer/Clipboard.js');
require('../utils/edit/isEditable.js');
require('../utils/edit/maxLength.js');
var getActiveElement = require('../utils/focus/getActiveElement.js');
var isFocusable = require('../utils/focus/isFocusable.js');
require('../utils/keyDef/readNextDescriptor.js');
var findClosest = require('../utils/misc/findClosest.js');
require('../utils/misc/level.js');
require('../options.js');
var updateSelectionOnFocus = require('./selection/updateSelectionOnFocus.js');
var wrapEvent = require('./wrapEvent.js');
/**
* Focus closest focusable element.
*/ function focusElement(element) {
const target = findClosest.findClosest(element, isFocusable.isFocusable);
const activeElement = getActiveElement.getActiveElement(element.ownerDocument);
if ((target !== null && target !== void 0 ? target : element.ownerDocument.body) === activeElement) {
return;
} else if (target) {
wrapEvent.wrapEvent(()=>target.focus());
} else {
wrapEvent.wrapEvent(()=>activeElement === null || activeElement === void 0 ? void 0 : activeElement.blur());
}
updateSelectionOnFocus.updateSelectionOnFocus(target !== null && target !== void 0 ? target : element.ownerDocument.body);
}
function blurElement(element) {
if (!isFocusable.isFocusable(element)) return;
const wasActive = getActiveElement.getActiveElement(element.ownerDocument) === element;
if (!wasActive) return;
wrapEvent.wrapEvent(()=>element.blur());
}
exports.blurElement = blurElement;
exports.focusElement = focusElement;

View File

@@ -0,0 +1,28 @@
'use strict';
var dispatchEvent = require('./dispatchEvent.js');
var focus = require('./focus.js');
var input = require('./input.js');
require('../utils/click/isClickableInput.js');
require('../utils/dataTransfer/Clipboard.js');
require('../utils/edit/isEditable.js');
require('../utils/edit/maxLength.js');
require('../utils/keyDef/readNextDescriptor.js');
require('../utils/misc/level.js');
require('../options.js');
var setSelectionPerMouse = require('./selection/setSelectionPerMouse.js');
var modifySelectionPerMouse = require('./selection/modifySelectionPerMouse.js');
var selectAll = require('./selection/selectAll.js');
exports.dispatchDOMEvent = dispatchEvent.dispatchDOMEvent;
exports.dispatchEvent = dispatchEvent.dispatchEvent;
exports.dispatchUIEvent = dispatchEvent.dispatchUIEvent;
exports.blurElement = focus.blurElement;
exports.focusElement = focus.focusElement;
exports.input = input.input;
exports.setSelectionPerMouseDown = setSelectionPerMouse.setSelectionPerMouseDown;
exports.modifySelectionPerMouseMove = modifySelectionPerMouse.modifySelectionPerMouseMove;
exports.isAllSelected = selectAll.isAllSelected;
exports.selectAll = selectAll.selectAll;

View File

@@ -0,0 +1,162 @@
'use strict';
var UI = require('../document/UI.js');
require('../utils/click/isClickableInput.js');
require('../utils/dataTransfer/Clipboard.js');
var timeValue = require('../utils/edit/timeValue.js');
require('../utils/edit/isEditable.js');
var maxLength = require('../utils/edit/maxLength.js');
var cursor = require('../utils/focus/cursor.js');
var isElementType = require('../utils/misc/isElementType.js');
require('../utils/keyDef/readNextDescriptor.js');
require('../utils/misc/level.js');
require('../options.js');
var trackValue = require('../document/trackValue.js');
var getInputRange = require('./selection/getInputRange.js');
var setSelection = require('./selection/setSelection.js');
function isDateOrTime(element) {
return isElementType.isElementType(element, 'input') && [
'date',
'time'
].includes(element.type);
}
function input(instance, element, data, inputType = 'insertText') {
const inputRange = getInputRange.getInputRange(element);
/* istanbul ignore if */ if (!inputRange) {
return;
}
// There is no `beforeinput` event on `date` and `time` input
if (!isDateOrTime(element)) {
const unprevented = instance.dispatchUIEvent(element, 'beforeinput', {
inputType,
data
});
if (!unprevented) {
return;
}
}
if ('startContainer' in inputRange) {
editContenteditable(instance, element, inputRange, data, inputType);
} else {
editInputElement(instance, element, inputRange, data, inputType);
}
}
function editContenteditable(instance, element, inputRange, data, inputType) {
let del = false;
if (!inputRange.collapsed) {
del = true;
inputRange.deleteContents();
} else if ([
'deleteContentBackward',
'deleteContentForward'
].includes(inputType)) {
const nextPosition = cursor.getNextCursorPosition(inputRange.startContainer, inputRange.startOffset, inputType === 'deleteContentBackward' ? -1 : 1, inputType);
if (nextPosition) {
del = true;
const delRange = inputRange.cloneRange();
if (delRange.comparePoint(nextPosition.node, nextPosition.offset) < 0) {
delRange.setStart(nextPosition.node, nextPosition.offset);
} else {
delRange.setEnd(nextPosition.node, nextPosition.offset);
}
delRange.deleteContents();
}
}
if (data) {
if (inputRange.endContainer.nodeType === 3) {
const offset = inputRange.endOffset;
inputRange.endContainer.insertData(offset, data);
inputRange.setStart(inputRange.endContainer, offset + data.length);
inputRange.setEnd(inputRange.endContainer, offset + data.length);
} else {
const text = element.ownerDocument.createTextNode(data);
inputRange.insertNode(text);
inputRange.setStart(text, data.length);
inputRange.setEnd(text, data.length);
}
}
if (del || data) {
instance.dispatchUIEvent(element, 'input', {
inputType
});
}
}
function editInputElement(instance, element, inputRange, data, inputType) {
let dataToInsert = data;
if (maxLength.supportsMaxLength(element)) {
const maxLength$1 = maxLength.getMaxLength(element);
if (maxLength$1 !== undefined && data.length > 0) {
const spaceUntilMaxLength = maxLength$1 - element.value.length;
if (spaceUntilMaxLength > 0) {
dataToInsert = data.substring(0, spaceUntilMaxLength);
} else {
return;
}
}
}
const { newValue, newOffset, oldValue } = calculateNewValue(dataToInsert, element, inputRange, inputType);
if (newValue === oldValue && newOffset === inputRange.startOffset && newOffset === inputRange.endOffset) {
return;
}
if (isElementType.isElementType(element, 'input', {
type: 'number'
}) && !isValidNumberInput(newValue)) {
return;
}
UI.setUIValue(element, newValue);
setSelection.setSelection({
focusNode: element,
anchorOffset: newOffset,
focusOffset: newOffset
});
if (isDateOrTime(element)) {
if (timeValue.isValidDateOrTimeValue(element, newValue)) {
commitInput(instance, element, newOffset, {});
instance.dispatchUIEvent(element, 'change');
UI.clearInitialValue(element);
}
} else {
commitInput(instance, element, newOffset, {
data,
inputType
});
}
}
function calculateNewValue(inputData, node, { startOffset, endOffset }, inputType) {
const value = UI.getUIValue(node);
const prologEnd = Math.max(0, startOffset === endOffset && inputType === 'deleteContentBackward' ? startOffset - 1 : startOffset);
const prolog = value.substring(0, prologEnd);
const epilogStart = Math.min(value.length, startOffset === endOffset && inputType === 'deleteContentForward' ? startOffset + 1 : endOffset);
const epilog = value.substring(epilogStart, value.length);
let newValue = `${prolog}${inputData}${epilog}`;
let newOffset = prologEnd + inputData.length;
if (isElementType.isElementType(node, 'input', {
type: 'time'
})) {
const builtValue = timeValue.buildTimeValue(newValue);
if (builtValue !== '' && timeValue.isValidDateOrTimeValue(node, builtValue)) {
newValue = builtValue;
newOffset = builtValue.length;
}
}
return {
oldValue: value,
newValue,
newOffset
};
}
function commitInput(instance, element, newOffset, inputInit) {
instance.dispatchUIEvent(element, 'input', inputInit);
trackValue.commitValueAfterInput(element, newOffset);
}
function isValidNumberInput(value) {
var _value_match, _value_match1;
// the browser allows some invalid input but not others
// it allows up to two '-' at any place before any 'e' or one directly following 'e'
// it allows one '.' at any place before e
const valueParts = value.split('e', 2);
return !(/[^\d.\-e]/.test(value) || Number((_value_match = value.match(/-/g)) === null || _value_match === void 0 ? void 0 : _value_match.length) > 2 || Number((_value_match1 = value.match(/\./g)) === null || _value_match1 === void 0 ? void 0 : _value_match1.length) > 1 || valueParts[1] && !/^-?\d*$/.test(valueParts[1]));
}
exports.input = input;

View File

@@ -0,0 +1,32 @@
'use strict';
require('../utils/click/isClickableInput.js');
require('../utils/dataTransfer/Clipboard.js');
require('../utils/edit/isEditable.js');
require('../utils/edit/maxLength.js');
var isDisabled = require('../utils/misc/isDisabled.js');
var getWindow = require('../utils/misc/getWindow.js');
require('../utils/keyDef/readNextDescriptor.js');
require('../utils/misc/level.js');
require('../options.js');
var focus = require('./focus.js');
function walkRadio(instance, el, direction) {
const window = getWindow.getWindow(el);
const group = Array.from(el.ownerDocument.querySelectorAll(el.name ? `input[type="radio"][name="${window.CSS.escape(el.name)}"]` : `input[type="radio"][name=""], input[type="radio"]:not([name])`));
for(let i = group.findIndex((e)=>e === el) + direction;; i += direction){
if (!group[i]) {
i = direction > 0 ? 0 : group.length - 1;
}
if (group[i] === el) {
return;
}
if (isDisabled.isDisabled(group[i])) {
continue;
}
focus.focusElement(group[i]);
instance.dispatchUIEvent(group[i], 'click');
}
}
exports.walkRadio = walkRadio;

View File

@@ -0,0 +1,18 @@
'use strict';
var getTargetTypeAndSelection = require('./getTargetTypeAndSelection.js');
/**
* Get the range that would be overwritten by input.
*/ function getInputRange(focusNode) {
const typeAndSelection = getTargetTypeAndSelection.getTargetTypeAndSelection(focusNode);
if (typeAndSelection.type === 'input') {
return typeAndSelection.selection;
} else if (typeAndSelection.type === 'contenteditable') {
var _typeAndSelection_selection;
// Multi-range on contenteditable edits the first selection instead of the last
return (_typeAndSelection_selection = typeAndSelection.selection) === null || _typeAndSelection_selection === void 0 ? void 0 : _typeAndSelection_selection.getRangeAt(0);
}
}
exports.getInputRange = getInputRange;

View File

@@ -0,0 +1,37 @@
'use strict';
var UI = require('../../document/UI.js');
require('../../utils/click/isClickableInput.js');
require('../../utils/dataTransfer/Clipboard.js');
var isContentEditable = require('../../utils/edit/isContentEditable.js');
require('../../utils/edit/isEditable.js');
require('../../utils/edit/maxLength.js');
var selection = require('../../utils/focus/selection.js');
require('../../utils/keyDef/readNextDescriptor.js');
require('../../utils/misc/level.js');
require('../../options.js');
/**
* Determine which selection logic and selection ranges to consider.
*/ function getTargetTypeAndSelection(node) {
const element = getElement(node);
if (element && selection.hasOwnSelection(element)) {
return {
type: 'input',
selection: UI.getUISelection(element)
};
}
const selection$1 = element === null || element === void 0 ? void 0 : element.ownerDocument.getSelection();
// It is possible to extend a single-range selection into a contenteditable.
// This results in the range acting like a range outside of contenteditable.
const isCE = isContentEditable.getContentEditable(node) && (selection$1 === null || selection$1 === void 0 ? void 0 : selection$1.anchorNode) && isContentEditable.getContentEditable(selection$1.anchorNode);
return {
type: isCE ? 'contenteditable' : 'default',
selection: selection$1
};
}
function getElement(node) {
return node.nodeType === 1 ? node : node.parentElement;
}
exports.getTargetTypeAndSelection = getTargetTypeAndSelection;

View File

@@ -0,0 +1,24 @@
'use strict';
var getInputRange = require('./getInputRange.js');
var modifySelection = require('./modifySelection.js');
var moveSelection = require('./moveSelection.js');
var setSelectionPerMouse = require('./setSelectionPerMouse.js');
var modifySelectionPerMouse = require('./modifySelectionPerMouse.js');
var selectAll = require('./selectAll.js');
var setSelectionRange = require('./setSelectionRange.js');
var setSelection = require('./setSelection.js');
var updateSelectionOnFocus = require('./updateSelectionOnFocus.js');
exports.getInputRange = getInputRange.getInputRange;
exports.modifySelection = modifySelection.modifySelection;
exports.moveSelection = moveSelection.moveSelection;
exports.setSelectionPerMouseDown = setSelectionPerMouse.setSelectionPerMouseDown;
exports.modifySelectionPerMouseMove = modifySelectionPerMouse.modifySelectionPerMouseMove;
exports.isAllSelected = selectAll.isAllSelected;
exports.selectAll = selectAll.selectAll;
exports.setSelectionRange = setSelectionRange.setSelectionRange;
exports.setSelection = setSelection.setSelection;
exports.updateSelectionOnFocus = updateSelectionOnFocus.updateSelectionOnFocus;

View File

@@ -0,0 +1,27 @@
'use strict';
var UI = require('../../document/UI.js');
require('../../utils/click/isClickableInput.js');
require('../../utils/dataTransfer/Clipboard.js');
require('../../utils/edit/isEditable.js');
require('../../utils/edit/maxLength.js');
require('../../utils/keyDef/readNextDescriptor.js');
require('../../utils/misc/level.js');
require('../../options.js');
var getTargetTypeAndSelection = require('./getTargetTypeAndSelection.js');
/**
* Extend/shrink the selection like with Shift+Arrows or Shift+Mouse
*/ function modifySelection({ focusNode, focusOffset }) {
var _focusNode_ownerDocument_getSelection, _focusNode_ownerDocument;
const typeAndSelection = getTargetTypeAndSelection.getTargetTypeAndSelection(focusNode);
if (typeAndSelection.type === 'input') {
return UI.setUISelection(focusNode, {
anchorOffset: typeAndSelection.selection.anchorOffset,
focusOffset
}, 'modify');
}
(_focusNode_ownerDocument = focusNode.ownerDocument) === null || _focusNode_ownerDocument === void 0 ? void 0 : (_focusNode_ownerDocument_getSelection = _focusNode_ownerDocument.getSelection()) === null || _focusNode_ownerDocument_getSelection === void 0 ? void 0 : _focusNode_ownerDocument_getSelection.extend(focusNode, focusOffset);
}
exports.modifySelection = modifySelection;

View File

@@ -0,0 +1,46 @@
'use strict';
var UI = require('../../document/UI.js');
require('../../utils/click/isClickableInput.js');
require('../../utils/dataTransfer/Clipboard.js');
require('../../utils/edit/isEditable.js');
require('../../utils/edit/maxLength.js');
require('../../utils/keyDef/readNextDescriptor.js');
require('../../utils/misc/level.js');
require('../../options.js');
var resolveCaretPosition = require('./resolveCaretPosition.js');
function modifySelectionPerMouseMove(selectionRange, { document, target, node, offset }) {
const selectionFocus = resolveCaretPosition.resolveCaretPosition({
target,
node,
offset
});
if ('node' in selectionRange) {
// When the mouse is dragged outside of an input/textarea,
// the selection is extended to the beginning or end of the input
// depending on pointer position.
// TODO: extend selection according to pointer position
/* istanbul ignore else */ if (selectionFocus.node === selectionRange.node) {
const anchorOffset = selectionFocus.offset < selectionRange.start ? selectionRange.end : selectionRange.start;
const focusOffset = selectionFocus.offset > selectionRange.end || selectionFocus.offset < selectionRange.start ? selectionFocus.offset : selectionRange.end;
UI.setUISelection(selectionRange.node, {
anchorOffset,
focusOffset
});
}
} else {
const range = selectionRange.cloneRange();
const cmp = range.comparePoint(selectionFocus.node, selectionFocus.offset);
if (cmp < 0) {
range.setStart(selectionFocus.node, selectionFocus.offset);
} else if (cmp > 0) {
range.setEnd(selectionFocus.node, selectionFocus.offset);
}
const selection = document.getSelection();
selection === null || selection === void 0 ? void 0 : selection.removeAllRanges();
selection === null || selection === void 0 ? void 0 : selection.addRange(range.cloneRange());
}
}
exports.modifySelectionPerMouseMove = modifySelectionPerMouseMove;

View File

@@ -0,0 +1,44 @@
'use strict';
var UI = require('../../document/UI.js');
require('../../utils/click/isClickableInput.js');
require('../../utils/dataTransfer/Clipboard.js');
require('../../utils/edit/isEditable.js');
require('../../utils/edit/maxLength.js');
var cursor = require('../../utils/focus/cursor.js');
var selection = require('../../utils/focus/selection.js');
require('../../utils/keyDef/readNextDescriptor.js');
require('../../utils/misc/level.js');
require('../../options.js');
var setSelection = require('./setSelection.js');
/**
* Move the selection
*/ function moveSelection(node, direction) {
// TODO: implement shift
if (selection.hasOwnSelection(node)) {
const selection = UI.getUISelection(node);
setSelection.setSelection({
focusNode: node,
focusOffset: selection.startOffset === selection.endOffset ? selection.focusOffset + direction : direction < 0 ? selection.startOffset : selection.endOffset
});
} else {
const selection = node.ownerDocument.getSelection();
if (!(selection === null || selection === void 0 ? void 0 : selection.focusNode)) {
return;
}
if (selection.isCollapsed) {
const nextPosition = cursor.getNextCursorPosition(selection.focusNode, selection.focusOffset, direction);
if (nextPosition) {
setSelection.setSelection({
focusNode: nextPosition.node,
focusOffset: nextPosition.offset
});
}
} else {
selection[direction < 0 ? 'collapseToStart' : 'collapseToEnd']();
}
}
}
exports.moveSelection = moveSelection;

View File

@@ -0,0 +1,67 @@
'use strict';
var UI = require('../../document/UI.js');
require('../../utils/click/isClickableInput.js');
require('../../utils/dataTransfer/Clipboard.js');
require('../../utils/edit/isEditable.js');
require('../../utils/edit/maxLength.js');
var selection = require('../../utils/focus/selection.js');
require('../../utils/keyDef/readNextDescriptor.js');
require('../../utils/misc/level.js');
require('../../options.js');
function resolveCaretPosition({ target, node, offset }) {
if (selection.hasOwnSelection(target)) {
return {
node: target,
offset: offset !== null && offset !== void 0 ? offset : UI.getUIValue(target).length
};
} else if (node) {
return {
node,
offset: offset !== null && offset !== void 0 ? offset : node.nodeType === 3 ? node.nodeValue.length : node.childNodes.length
};
}
return findNodeAtTextOffset(target, offset);
}
function findNodeAtTextOffset(node, offset, isRoot = true) {
// When clicking after the content the browser behavior can be complicated:
// 1. If there is textContent after the last element child,
// the cursor is moved there.
// 2. If there is textContent in the last element child,
// the browser moves the cursor to the last non-empty text node inside this element.
// 3. Otherwise the cursor is moved to the end of the target.
let i = offset === undefined ? node.childNodes.length - 1 : 0;
const step = offset === undefined ? -1 : +1;
while(offset === undefined ? i >= (isRoot ? Math.max(node.childNodes.length - 1, 0) : 0) : i <= node.childNodes.length){
if (offset && i === node.childNodes.length) {
throw new Error('The given offset is out of bounds.');
}
const c = node.childNodes.item(i);
const text = String(c.textContent);
if (text.length) {
if (offset !== undefined && text.length < offset) {
offset -= text.length;
} else if (c.nodeType === 1) {
return findNodeAtTextOffset(c, offset, false);
} else {
// The pre-commit hooks keeps changing this
// See https://github.com/kentcdodds/kcd-scripts/issues/218
/* istanbul ignore else */ // eslint-disable-next-line no-lonely-if
if (c.nodeType === 3) {
return {
node: c,
offset: offset !== null && offset !== void 0 ? offset : c.nodeValue.length
};
}
}
}
i += step;
}
return {
node,
offset: node.childNodes.length
};
}
exports.resolveCaretPosition = resolveCaretPosition;

View File

@@ -0,0 +1,44 @@
'use strict';
var UI = require('../../document/UI.js');
require('../../utils/click/isClickableInput.js');
require('../../utils/dataTransfer/Clipboard.js');
var isContentEditable = require('../../utils/edit/isContentEditable.js');
require('../../utils/edit/isEditable.js');
require('../../utils/edit/maxLength.js');
var selection = require('../../utils/focus/selection.js');
require('../../utils/keyDef/readNextDescriptor.js');
require('../../utils/misc/level.js');
require('../../options.js');
var setSelection = require('./setSelection.js');
/**
* Expand a selection like the browser does when pressing Ctrl+A.
*/ function selectAll(target) {
if (selection.hasOwnSelection(target)) {
return setSelection.setSelection({
focusNode: target,
anchorOffset: 0,
focusOffset: UI.getUIValue(target).length
});
}
var _getContentEditable;
const focusNode = (_getContentEditable = isContentEditable.getContentEditable(target)) !== null && _getContentEditable !== void 0 ? _getContentEditable : target.ownerDocument.body;
setSelection.setSelection({
focusNode,
anchorOffset: 0,
focusOffset: focusNode.childNodes.length
});
}
function isAllSelected(target) {
if (selection.hasOwnSelection(target)) {
return UI.getUISelection(target).startOffset === 0 && UI.getUISelection(target).endOffset === UI.getUIValue(target).length;
}
var _getContentEditable;
const focusNode = (_getContentEditable = isContentEditable.getContentEditable(target)) !== null && _getContentEditable !== void 0 ? _getContentEditable : target.ownerDocument.body;
const selection$1 = target.ownerDocument.getSelection();
return (selection$1 === null || selection$1 === void 0 ? void 0 : selection$1.anchorNode) === focusNode && selection$1.focusNode === focusNode && selection$1.anchorOffset === 0 && selection$1.focusOffset === focusNode.childNodes.length;
}
exports.isAllSelected = isAllSelected;
exports.selectAll = selectAll;

View File

@@ -0,0 +1,27 @@
'use strict';
var UI = require('../../document/UI.js');
require('../../utils/click/isClickableInput.js');
require('../../utils/dataTransfer/Clipboard.js');
require('../../utils/edit/isEditable.js');
require('../../utils/edit/maxLength.js');
require('../../utils/keyDef/readNextDescriptor.js');
require('../../utils/misc/level.js');
require('../../options.js');
var getTargetTypeAndSelection = require('./getTargetTypeAndSelection.js');
/**
* Set the selection
*/ function setSelection({ focusNode, focusOffset, anchorNode = focusNode, anchorOffset = focusOffset }) {
var _anchorNode_ownerDocument_getSelection, _anchorNode_ownerDocument;
const typeAndSelection = getTargetTypeAndSelection.getTargetTypeAndSelection(focusNode);
if (typeAndSelection.type === 'input') {
return UI.setUISelection(focusNode, {
anchorOffset,
focusOffset
});
}
(_anchorNode_ownerDocument = anchorNode.ownerDocument) === null || _anchorNode_ownerDocument === void 0 ? void 0 : (_anchorNode_ownerDocument_getSelection = _anchorNode_ownerDocument.getSelection()) === null || _anchorNode_ownerDocument_getSelection === void 0 ? void 0 : _anchorNode_ownerDocument_getSelection.setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset);
}
exports.setSelection = setSelection;

View File

@@ -0,0 +1,87 @@
'use strict';
var UI = require('../../document/UI.js');
require('../../utils/click/isClickableInput.js');
require('../../utils/dataTransfer/Clipboard.js');
require('../../utils/edit/isEditable.js');
require('../../utils/edit/maxLength.js');
var selection = require('../../utils/focus/selection.js');
require('../../utils/keyDef/readNextDescriptor.js');
require('../../utils/misc/level.js');
require('../../options.js');
var resolveCaretPosition = require('./resolveCaretPosition.js');
function setSelectionPerMouseDown({ document, target, clickCount, node, offset }) {
if (selection.hasNoSelection(target)) {
return;
}
const targetHasOwnSelection = selection.hasOwnSelection(target);
// On non-input elements the text selection per multiple click
// can extend beyond the target boundaries.
// The exact mechanism what is considered in the same line is unclear.
// Looks it might be every inline element.
// TODO: Check what might be considered part of the same line of text.
const text = String(targetHasOwnSelection ? UI.getUIValue(target) : target.textContent);
const [start, end] = node ? // which elements might be considered in the same line of text.
// TODO: support expanding initial range on multiple clicks if node is given
[
offset,
offset
] : getTextRange(text, offset, clickCount);
// TODO: implement modifying selection per shift/ctrl+mouse
if (targetHasOwnSelection) {
UI.setUISelection(target, {
anchorOffset: start !== null && start !== void 0 ? start : text.length,
focusOffset: end !== null && end !== void 0 ? end : text.length
});
return {
node: target,
start: start !== null && start !== void 0 ? start : 0,
end: end !== null && end !== void 0 ? end : text.length
};
} else {
const { node: startNode, offset: startOffset } = resolveCaretPosition.resolveCaretPosition({
target,
node,
offset: start
});
const { node: endNode, offset: endOffset } = resolveCaretPosition.resolveCaretPosition({
target,
node,
offset: end
});
const range = target.ownerDocument.createRange();
try {
range.setStart(startNode, startOffset);
range.setEnd(endNode, endOffset);
} catch (e) {
throw new Error('The given offset is out of bounds.');
}
const selection = document.getSelection();
selection === null || selection === void 0 ? void 0 : selection.removeAllRanges();
selection === null || selection === void 0 ? void 0 : selection.addRange(range.cloneRange());
return range;
}
}
function getTextRange(text, pos, clickCount) {
if (clickCount % 3 === 1 || text.length === 0) {
return [
pos,
pos
];
}
const textPos = pos !== null && pos !== void 0 ? pos : text.length;
if (clickCount % 3 === 2) {
return [
textPos - text.substr(0, pos).match(/(\w+|\s+|\W)?$/)[0].length,
pos === undefined ? pos : pos + text.substr(pos).match(/^(\w+|\s+|\W)?/)[0].length
];
}
// triple click
return [
textPos - text.substr(0, pos).match(/[^\r\n]*$/)[0].length,
pos === undefined ? pos : pos + text.substr(pos).match(/^[^\r\n]*/)[0].length
];
}
exports.setSelectionPerMouseDown = setSelectionPerMouseDown;

View File

@@ -0,0 +1,37 @@
'use strict';
require('../../utils/click/isClickableInput.js');
require('../../utils/dataTransfer/Clipboard.js');
var isContentEditable = require('../../utils/edit/isContentEditable.js');
require('../../utils/edit/isEditable.js');
require('../../utils/edit/maxLength.js');
var selection = require('../../utils/focus/selection.js');
require('../../utils/keyDef/readNextDescriptor.js');
require('../../utils/misc/level.js');
require('../../options.js');
var setSelection = require('./setSelection.js');
/**
* Backward-compatible selection.
*
* Handles input elements and contenteditable if it only contains a single text node.
*/ function setSelectionRange(element, anchorOffset, focusOffset) {
var _element_firstChild;
if (selection.hasOwnSelection(element)) {
return setSelection.setSelection({
focusNode: element,
anchorOffset,
focusOffset
});
}
/* istanbul ignore else */ if (isContentEditable.isContentEditable(element) && ((_element_firstChild = element.firstChild) === null || _element_firstChild === void 0 ? void 0 : _element_firstChild.nodeType) === 3) {
return setSelection.setSelection({
focusNode: element.firstChild,
anchorOffset,
focusOffset
});
}
/* istanbul ignore next */ throw new Error('Not implemented. The result of this interaction is unreliable.');
}
exports.setSelectionRange = setSelectionRange;

View File

@@ -0,0 +1,42 @@
'use strict';
require('../../utils/click/isClickableInput.js');
require('../../utils/dataTransfer/Clipboard.js');
var isContentEditable = require('../../utils/edit/isContentEditable.js');
require('../../utils/edit/isEditable.js');
require('../../utils/edit/maxLength.js');
var selection = require('../../utils/focus/selection.js');
require('../../utils/keyDef/readNextDescriptor.js');
require('../../utils/misc/level.js');
require('../../options.js');
/**
* Reset the Document Selection when moving focus into an element
* with own selection implementation.
*/ function updateSelectionOnFocus(element) {
const selection$1 = element.ownerDocument.getSelection();
/* istanbul ignore if */ if (!(selection$1 === null || selection$1 === void 0 ? void 0 : selection$1.focusNode)) {
return;
}
// If the focus moves inside an element with own selection implementation,
// the document selection will be this element.
// But if the focused element is inside a contenteditable,
// 1) a collapsed selection will be retained.
// 2) other selections will be replaced by a cursor
// 2.a) at the start of the first child if it is a text node
// 2.b) at the start of the contenteditable.
if (selection.hasOwnSelection(element)) {
const contenteditable = isContentEditable.getContentEditable(selection$1.focusNode);
if (contenteditable) {
if (!selection$1.isCollapsed) {
var _contenteditable_firstChild;
const focusNode = ((_contenteditable_firstChild = contenteditable.firstChild) === null || _contenteditable_firstChild === void 0 ? void 0 : _contenteditable_firstChild.nodeType) === 3 ? contenteditable.firstChild : contenteditable;
selection$1.setBaseAndExtent(focusNode, 0, focusNode, 0);
}
} else {
selection$1.setBaseAndExtent(element, 0, element, 0);
}
}
}
exports.updateSelectionOnFocus = updateSelectionOnFocus;

View File

@@ -0,0 +1,2 @@
'use strict';

View File

@@ -0,0 +1,9 @@
'use strict';
var dom = require('@testing-library/dom');
function wrapEvent(cb, _element) {
return dom.getConfig().eventWrapper(cb);
}
exports.wrapEvent = wrapEvent;

View File

@@ -0,0 +1,15 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var index = require('./setup/index.js');
var options = require('./options.js');
exports.default = index.userEvent;
exports.userEvent = index.userEvent;
Object.defineProperty(exports, "PointerEventsCheckLevel", {
enumerable: true,
get: function () { return options.PointerEventsCheckLevel; }
});

View File

@@ -0,0 +1,46 @@
'use strict';
require('../utils/click/isClickableInput.js');
require('../utils/dataTransfer/Clipboard.js');
require('../utils/edit/isEditable.js');
require('../utils/edit/maxLength.js');
require('../utils/keyDef/readNextDescriptor.js');
require('../utils/misc/level.js');
var wait = require('../utils/misc/wait.js');
require('../options.js');
var parseKeyDef = require('./parseKeyDef.js');
async function keyboard(text) {
const actions = parseKeyDef.parseKeyDef(this.config.keyboardMap, text);
for(let i = 0; i < actions.length; i++){
await wait.wait(this.config);
await keyboardAction(this, actions[i]);
}
}
async function keyboardAction(instance, { keyDef, releasePrevious, releaseSelf, repeat }) {
const { system } = instance;
// Release the key automatically if it was pressed before.
if (system.keyboard.isKeyPressed(keyDef)) {
await system.keyboard.keyup(instance, keyDef);
}
if (!releasePrevious) {
for(let i = 1; i <= repeat; i++){
await system.keyboard.keydown(instance, keyDef);
if (i < repeat) {
await wait.wait(instance.config);
}
}
// Release the key only on the last iteration on `state.repeatKey`.
if (releaseSelf) {
await system.keyboard.keyup(instance, keyDef);
}
}
}
async function releaseAllKeys(instance) {
for (const k of instance.system.keyboard.getPressedKeys()){
await instance.system.keyboard.keyup(instance, k);
}
}
exports.keyboard = keyboard;
exports.releaseAllKeys = releaseAllKeys;

View File

@@ -0,0 +1,156 @@
'use strict';
var keyboard = require('../system/keyboard.js');
/**
* Mapping for a default US-104-QWERTY keyboard
*/ const defaultKeyMap = [
// alphanumeric keys
...'0123456789'.split('').map((c)=>({
code: `Digit${c}`,
key: c
})),
...')!@#$%^&*('.split('').map((c, i)=>({
code: `Digit${i}`,
key: c,
shiftKey: true
})),
...'abcdefghijklmnopqrstuvwxyz'.split('').map((c)=>({
code: `Key${c.toUpperCase()}`,
key: c
})),
...'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('').map((c)=>({
code: `Key${c}`,
key: c,
shiftKey: true
})),
// alphanumeric block - functional
{
code: 'Space',
key: ' '
},
{
code: 'AltLeft',
key: 'Alt',
location: keyboard.DOM_KEY_LOCATION.LEFT
},
{
code: 'AltRight',
key: 'Alt',
location: keyboard.DOM_KEY_LOCATION.RIGHT
},
{
code: 'ShiftLeft',
key: 'Shift',
location: keyboard.DOM_KEY_LOCATION.LEFT
},
{
code: 'ShiftRight',
key: 'Shift',
location: keyboard.DOM_KEY_LOCATION.RIGHT
},
{
code: 'ControlLeft',
key: 'Control',
location: keyboard.DOM_KEY_LOCATION.LEFT
},
{
code: 'ControlRight',
key: 'Control',
location: keyboard.DOM_KEY_LOCATION.RIGHT
},
{
code: 'MetaLeft',
key: 'Meta',
location: keyboard.DOM_KEY_LOCATION.LEFT
},
{
code: 'MetaRight',
key: 'Meta',
location: keyboard.DOM_KEY_LOCATION.RIGHT
},
{
code: 'OSLeft',
key: 'OS',
location: keyboard.DOM_KEY_LOCATION.LEFT
},
{
code: 'OSRight',
key: 'OS',
location: keyboard.DOM_KEY_LOCATION.RIGHT
},
{
code: 'Tab',
key: 'Tab'
},
{
code: 'CapsLock',
key: 'CapsLock'
},
{
code: 'Backspace',
key: 'Backspace'
},
{
code: 'Enter',
key: 'Enter'
},
// function
{
code: 'Escape',
key: 'Escape'
},
// arrows
{
code: 'ArrowUp',
key: 'ArrowUp'
},
{
code: 'ArrowDown',
key: 'ArrowDown'
},
{
code: 'ArrowLeft',
key: 'ArrowLeft'
},
{
code: 'ArrowRight',
key: 'ArrowRight'
},
// control pad
{
code: 'Home',
key: 'Home'
},
{
code: 'End',
key: 'End'
},
{
code: 'Delete',
key: 'Delete'
},
{
code: 'PageUp',
key: 'PageUp'
},
{
code: 'PageDown',
key: 'PageDown'
},
// Special keys that are not part of a default US-layout but included for specific behavior
{
code: 'Fn',
key: 'Fn'
},
{
code: 'Symbol',
key: 'Symbol'
},
{
code: 'AltRight',
key: 'AltGraph'
}
];
exports.defaultKeyMap = defaultKeyMap;

View File

@@ -0,0 +1,50 @@
'use strict';
require('../utils/click/isClickableInput.js');
require('../utils/dataTransfer/Clipboard.js');
require('../utils/edit/isEditable.js');
require('../utils/edit/maxLength.js');
var readNextDescriptor = require('../utils/keyDef/readNextDescriptor.js');
require('../utils/misc/level.js');
require('../options.js');
/**
* Parse key defintions per `keyboardMap`
*
* Keys can be referenced by `{key}` or `{special}` as well as physical locations per `[code]`.
* Everything else will be interpreted as a typed character - e.g. `a`.
* Brackets `{` and `[` can be escaped by doubling - e.g. `foo[[bar` translates to `foo[bar`.
* Keeping the key pressed can be written as `{key>}`.
* When keeping the key pressed you can choose how long (how many keydown and keypress) the key is pressed `{key>3}`.
* You can then release the key per `{key>3/}` or keep it pressed and continue with the next key.
*/ function parseKeyDef(keyboardMap, text) {
const defs = [];
do {
const { type, descriptor, consumedLength, releasePrevious, releaseSelf = true, repeat } = readNextDescriptor.readNextDescriptor(text, 'keyboard');
var _keyboardMap_find;
const keyDef = (_keyboardMap_find = keyboardMap.find((def)=>{
if (type === '[') {
var _def_code;
return ((_def_code = def.code) === null || _def_code === void 0 ? void 0 : _def_code.toLowerCase()) === descriptor.toLowerCase();
} else if (type === '{') {
var _def_key;
return ((_def_key = def.key) === null || _def_key === void 0 ? void 0 : _def_key.toLowerCase()) === descriptor.toLowerCase();
}
return def.key === descriptor;
})) !== null && _keyboardMap_find !== void 0 ? _keyboardMap_find : {
key: 'Unknown',
code: 'Unknown',
[type === '[' ? 'code' : 'key']: descriptor
};
defs.push({
keyDef,
releasePrevious,
releaseSelf,
repeat
});
text = text.slice(consumedLength);
}while (text)
return defs;
}
exports.parseKeyDef = parseKeyDef;

View File

@@ -0,0 +1,12 @@
'use strict';
exports.PointerEventsCheckLevel = void 0;
(function(PointerEventsCheckLevel) {
/**
* Check pointer events on every user interaction that triggers a bunch of events.
* E.g. once for releasing a mouse button even though this triggers `pointerup`, `mouseup`, `click`, etc...
*/ PointerEventsCheckLevel[PointerEventsCheckLevel["EachTrigger"] = 4] = "EachTrigger";
/** Check each target once per call to pointer (related) API */ PointerEventsCheckLevel[PointerEventsCheckLevel["EachApiCall"] = 2] = "EachApiCall";
/** Check each event target once */ PointerEventsCheckLevel[PointerEventsCheckLevel["EachTarget"] = 1] = "EachTarget";
/** No pointer events check */ PointerEventsCheckLevel[PointerEventsCheckLevel["Never"] = 0] = "Never";
})(exports.PointerEventsCheckLevel || (exports.PointerEventsCheckLevel = {}));

View File

@@ -0,0 +1,3 @@
{
"type": "commonjs"
}

View File

@@ -0,0 +1,79 @@
'use strict';
require('../utils/click/isClickableInput.js');
require('../utils/dataTransfer/Clipboard.js');
require('../utils/edit/isEditable.js');
require('../utils/edit/maxLength.js');
require('../utils/keyDef/readNextDescriptor.js');
var level = require('../utils/misc/level.js');
var wait = require('../utils/misc/wait.js');
require('../options.js');
var parseKeyDef = require('./parseKeyDef.js');
async function pointer(input) {
const { pointerMap } = this.config;
const actions = [];
(Array.isArray(input) ? input : [
input
]).forEach((actionInput)=>{
if (typeof actionInput === 'string') {
actions.push(...parseKeyDef.parseKeyDef(pointerMap, actionInput));
} else if ('keys' in actionInput) {
actions.push(...parseKeyDef.parseKeyDef(pointerMap, actionInput.keys).map((i)=>({
...actionInput,
...i
})));
} else {
actions.push(actionInput);
}
});
for(let i = 0; i < actions.length; i++){
await wait.wait(this.config);
await pointerAction(this, actions[i]);
}
this.system.pointer.resetClickCount();
}
async function pointerAction(instance, action) {
var _previousPosition_caret, _previousPosition_caret1;
const pointerName = 'pointerName' in action && action.pointerName ? action.pointerName : 'keyDef' in action ? instance.system.pointer.getPointerName(action.keyDef) : 'mouse';
const previousPosition = instance.system.pointer.getPreviousPosition(pointerName);
var _action_target, _action_coords, _action_node, _action_offset;
const position = {
target: (_action_target = action.target) !== null && _action_target !== void 0 ? _action_target : getPrevTarget(instance, previousPosition),
coords: (_action_coords = action.coords) !== null && _action_coords !== void 0 ? _action_coords : previousPosition === null || previousPosition === void 0 ? void 0 : previousPosition.coords,
caret: {
node: (_action_node = action.node) !== null && _action_node !== void 0 ? _action_node : hasCaretPosition(action) ? undefined : previousPosition === null || previousPosition === void 0 ? void 0 : (_previousPosition_caret = previousPosition.caret) === null || _previousPosition_caret === void 0 ? void 0 : _previousPosition_caret.node,
offset: (_action_offset = action.offset) !== null && _action_offset !== void 0 ? _action_offset : hasCaretPosition(action) ? undefined : previousPosition === null || previousPosition === void 0 ? void 0 : (_previousPosition_caret1 = previousPosition.caret) === null || _previousPosition_caret1 === void 0 ? void 0 : _previousPosition_caret1.offset
}
};
if ('keyDef' in action) {
if (instance.system.pointer.isKeyPressed(action.keyDef)) {
level.setLevelRef(instance, level.ApiLevel.Trigger);
await instance.system.pointer.release(instance, action.keyDef, position);
}
if (!action.releasePrevious) {
level.setLevelRef(instance, level.ApiLevel.Trigger);
await instance.system.pointer.press(instance, action.keyDef, position);
if (action.releaseSelf) {
level.setLevelRef(instance, level.ApiLevel.Trigger);
await instance.system.pointer.release(instance, action.keyDef, position);
}
}
} else {
level.setLevelRef(instance, level.ApiLevel.Trigger);
await instance.system.pointer.move(instance, pointerName, position);
}
}
function hasCaretPosition(action) {
var _action_target, _ref;
return !!((_ref = (_action_target = action.target) !== null && _action_target !== void 0 ? _action_target : action.node) !== null && _ref !== void 0 ? _ref : action.offset !== undefined);
}
function getPrevTarget(instance, position) {
if (!position) {
throw new Error('This pointer has no previous position. Provide a target property!');
}
var _position_target;
return (_position_target = position.target) !== null && _position_target !== void 0 ? _position_target : instance.config.document.body;
}
exports.pointer = pointer;

View File

@@ -0,0 +1,33 @@
'use strict';
const defaultKeyMap = [
{
name: 'MouseLeft',
pointerType: 'mouse',
button: 'primary'
},
{
name: 'MouseRight',
pointerType: 'mouse',
button: 'secondary'
},
{
name: 'MouseMiddle',
pointerType: 'mouse',
button: 'auxiliary'
},
{
name: 'TouchA',
pointerType: 'touch'
},
{
name: 'TouchB',
pointerType: 'touch'
},
{
name: 'TouchC',
pointerType: 'touch'
}
];
exports.defaultKeyMap = defaultKeyMap;

View File

@@ -0,0 +1,28 @@
'use strict';
require('../utils/click/isClickableInput.js');
require('../utils/dataTransfer/Clipboard.js');
require('../utils/edit/isEditable.js');
require('../utils/edit/maxLength.js');
var readNextDescriptor = require('../utils/keyDef/readNextDescriptor.js');
require('../utils/misc/level.js');
require('../options.js');
function parseKeyDef(pointerMap, keys) {
const defs = [];
do {
const { descriptor, consumedLength, releasePrevious, releaseSelf = true } = readNextDescriptor.readNextDescriptor(keys, 'pointer');
const keyDef = pointerMap.find((p)=>p.name === descriptor);
if (keyDef) {
defs.push({
keyDef,
releasePrevious,
releaseSelf
});
}
keys = keys.slice(consumedLength);
}while (keys)
return defs;
}
exports.parseKeyDef = parseKeyDef;

View File

@@ -0,0 +1,35 @@
'use strict';
var click = require('../convenience/click.js');
var hover = require('../convenience/hover.js');
var tab = require('../convenience/tab.js');
var index = require('../keyboard/index.js');
var copy = require('../clipboard/copy.js');
var cut = require('../clipboard/cut.js');
var paste = require('../clipboard/paste.js');
var index$1 = require('../pointer/index.js');
var clear = require('../utility/clear.js');
var selectOptions = require('../utility/selectOptions.js');
var type = require('../utility/type.js');
var upload = require('../utility/upload.js');
const userEventApi = {
click: click.click,
dblClick: click.dblClick,
tripleClick: click.tripleClick,
hover: hover.hover,
unhover: hover.unhover,
tab: tab.tab,
keyboard: index.keyboard,
copy: copy.copy,
cut: cut.cut,
paste: paste.paste,
pointer: index$1.pointer,
clear: clear.clear,
deselectOptions: selectOptions.deselectOptions,
selectOptions: selectOptions.selectOptions,
type: type.type,
upload: upload.upload
};
exports.userEventApi = userEventApi;

View File

@@ -0,0 +1,75 @@
'use strict';
var setup = require('./setup.js');
function clear(element) {
return setup.setupDirect().api.clear(element);
}
function click(element, options = {}) {
return setup.setupDirect(options, element).api.click(element);
}
function copy(options = {}) {
return setup.setupDirect(options).api.copy();
}
function cut(options = {}) {
return setup.setupDirect(options).api.cut();
}
function dblClick(element, options = {}) {
return setup.setupDirect(options).api.dblClick(element);
}
function deselectOptions(select, values, options = {}) {
return setup.setupDirect(options).api.deselectOptions(select, values);
}
function hover(element, options = {}) {
return setup.setupDirect(options).api.hover(element);
}
async function keyboard(text, options = {}) {
const { api, system } = setup.setupDirect(options);
return api.keyboard(text).then(()=>system);
}
async function pointer(input, options = {}) {
const { api, system } = setup.setupDirect(options);
return api.pointer(input).then(()=>system);
}
function paste(clipboardData, options) {
return setup.setupDirect(options).api.paste(clipboardData);
}
function selectOptions(select, values, options = {}) {
return setup.setupDirect(options).api.selectOptions(select, values);
}
function tripleClick(element, options = {}) {
return setup.setupDirect(options).api.tripleClick(element);
}
function type(element, text, options = {}) {
return setup.setupDirect(options, element).api.type(element, text, options);
}
function unhover(element, options = {}) {
const { api, system } = setup.setupDirect(options);
system.pointer.setMousePosition({
target: element
});
return api.unhover(element);
}
function upload(element, fileOrFiles, options = {}) {
return setup.setupDirect(options).api.upload(element, fileOrFiles);
}
function tab(options = {}) {
return setup.setupDirect().api.tab(options);
}
exports.clear = clear;
exports.click = click;
exports.copy = copy;
exports.cut = cut;
exports.dblClick = dblClick;
exports.deselectOptions = deselectOptions;
exports.hover = hover;
exports.keyboard = keyboard;
exports.paste = paste;
exports.pointer = pointer;
exports.selectOptions = selectOptions;
exports.tab = tab;
exports.tripleClick = tripleClick;
exports.type = type;
exports.unhover = unhover;
exports.upload = upload;

View File

@@ -0,0 +1,11 @@
'use strict';
var setup = require('./setup.js');
var directApi = require('./directApi.js');
const userEvent = {
...directApi,
setup: setup.setupMain
};
exports.userEvent = userEvent;

View File

@@ -0,0 +1,125 @@
'use strict';
var prepareDocument = require('../document/prepareDocument.js');
var dispatchEvent = require('../event/dispatchEvent.js');
require('../utils/click/isClickableInput.js');
var Clipboard = require('../utils/dataTransfer/Clipboard.js');
require('../utils/edit/isEditable.js');
require('../utils/edit/maxLength.js');
require('../utils/keyDef/readNextDescriptor.js');
var getDocumentFromNode = require('../utils/misc/getDocumentFromNode.js');
var level = require('../utils/misc/level.js');
var wait = require('../utils/misc/wait.js');
var options = require('../options.js');
require('@testing-library/dom');
var keyMap = require('../keyboard/keyMap.js');
var keyMap$1 = require('../pointer/keyMap.js');
var index = require('../system/index.js');
var api = require('./api.js');
var wrapAsync = require('./wrapAsync.js');
/**
* Default options applied when API is called per `userEvent.anyApi()`
*/ const defaultOptionsDirect = {
applyAccept: true,
autoModify: true,
delay: 0,
document: globalThis.document,
keyboardMap: keyMap.defaultKeyMap,
pointerMap: keyMap$1.defaultKeyMap,
pointerEventsCheck: options.PointerEventsCheckLevel.EachApiCall,
skipAutoClose: false,
skipClick: false,
skipHover: false,
writeToClipboard: false,
advanceTimers: ()=>Promise.resolve()
};
/**
* Default options applied when API is called per `userEvent().anyApi()`
*/ const defaultOptionsSetup = {
...defaultOptionsDirect,
writeToClipboard: true
};
function createConfig(options = {}, defaults = defaultOptionsSetup, node) {
const document = getDocument(options, node, defaults);
return {
...defaults,
...options,
document
};
}
/**
* Start a "session" with userEvent.
* All APIs returned by this function share an input device state and a default configuration.
*/ function setupMain(options = {}) {
const config = createConfig(options);
prepareDocument.prepareDocument(config.document);
var _config_document_defaultView;
const view = (_config_document_defaultView = config.document.defaultView) !== null && _config_document_defaultView !== void 0 ? _config_document_defaultView : /* istanbul ignore next */ globalThis.window;
Clipboard.attachClipboardStubToView(view);
return createInstance(config).api;
}
/**
* Setup in direct call per `userEvent.anyApi()`
*/ function setupDirect({ keyboardState, pointerState, ...options } = {}, node) {
const config = createConfig(options, defaultOptionsDirect, node);
prepareDocument.prepareDocument(config.document);
var _ref;
const system = (_ref = pointerState !== null && pointerState !== void 0 ? pointerState : keyboardState) !== null && _ref !== void 0 ? _ref : new index.System();
return {
api: createInstance(config, system).api,
system
};
}
/**
* Create a set of callbacks with different default settings but the same state.
*/ function setupSub(options) {
return createInstance({
...this.config,
...options
}, this.system).api;
}
function wrapAndBindImpl(instance, impl) {
function method(...args) {
level.setLevelRef(instance, level.ApiLevel.Call);
return wrapAsync.wrapAsync(()=>impl.apply(instance, args).then(async (ret)=>{
await wait.wait(instance.config);
return ret;
}));
}
Object.defineProperty(method, 'name', {
get: ()=>impl.name
});
return method;
}
function createInstance(config, system = new index.System()) {
const instance = {};
Object.assign(instance, {
config,
dispatchEvent: dispatchEvent.dispatchEvent.bind(instance),
dispatchUIEvent: dispatchEvent.dispatchUIEvent.bind(instance),
system,
levelRefs: {},
...api.userEventApi
});
return {
instance,
api: {
...Object.fromEntries(Object.entries(api.userEventApi).map(([name, api])=>[
name,
wrapAndBindImpl(instance, api)
])),
setup: setupSub.bind(instance)
}
};
}
function getDocument(options, node, defaults) {
var _options_document, _ref;
return (_ref = (_options_document = options.document) !== null && _options_document !== void 0 ? _options_document : node && getDocumentFromNode.getDocumentFromNode(node)) !== null && _ref !== void 0 ? _ref : defaults.document;
}
exports.createConfig = createConfig;
exports.createInstance = createInstance;
exports.setupDirect = setupDirect;
exports.setupMain = setupMain;
exports.setupSub = setupSub;

View File

@@ -0,0 +1,11 @@
'use strict';
var dom = require('@testing-library/dom');
/**
* Wrap an internal Promise
*/ function wrapAsync(implementation) {
return dom.getConfig().asyncWrapper(implementation);
}
exports.wrapAsync = wrapAsync;

View File

@@ -0,0 +1,44 @@
'use strict';
var keyboard = require('./keyboard.js');
var index = require('./pointer/index.js');
function _define_property(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
/**
* @internal Do not create/alter this by yourself as this type might be subject to changes.
*/ class System {
getUIEventModifiers() {
return {
altKey: this.keyboard.modifiers.Alt,
ctrlKey: this.keyboard.modifiers.Control,
metaKey: this.keyboard.modifiers.Meta,
shiftKey: this.keyboard.modifiers.Shift,
modifierAltGraph: this.keyboard.modifiers.AltGraph,
modifierCapsLock: this.keyboard.modifiers.CapsLock,
modifierFn: this.keyboard.modifiers.Fn,
modifierFnLock: this.keyboard.modifiers.FnLock,
modifierNumLock: this.keyboard.modifiers.NumLock,
modifierScrollLock: this.keyboard.modifiers.ScrollLock,
modifierSymbol: this.keyboard.modifiers.Symbol,
modifierSymbolLock: this.keyboard.modifiers.SymbolLock
};
}
constructor(){
_define_property(this, "keyboard", new keyboard.KeyboardHost(this));
_define_property(this, "pointer", new index.PointerHost(this));
}
}
exports.System = System;

View File

@@ -0,0 +1,147 @@
'use strict';
require('../utils/click/isClickableInput.js');
require('../utils/dataTransfer/Clipboard.js');
require('../utils/edit/isEditable.js');
require('../utils/edit/maxLength.js');
var getActiveElement = require('../utils/focus/getActiveElement.js');
require('../utils/keyDef/readNextDescriptor.js');
require('../utils/misc/level.js');
require('../options.js');
function _define_property(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
exports.DOM_KEY_LOCATION = void 0;
(function(DOM_KEY_LOCATION) {
DOM_KEY_LOCATION[DOM_KEY_LOCATION["STANDARD"] = 0] = "STANDARD";
DOM_KEY_LOCATION[DOM_KEY_LOCATION["LEFT"] = 1] = "LEFT";
DOM_KEY_LOCATION[DOM_KEY_LOCATION["RIGHT"] = 2] = "RIGHT";
DOM_KEY_LOCATION[DOM_KEY_LOCATION["NUMPAD"] = 3] = "NUMPAD";
})(exports.DOM_KEY_LOCATION || (exports.DOM_KEY_LOCATION = {}));
const modifierKeys = [
'Alt',
'AltGraph',
'Control',
'Fn',
'Meta',
'Shift',
'Symbol'
];
function isModifierKey(key) {
return modifierKeys.includes(key);
}
const modifierLocks = [
'CapsLock',
'FnLock',
'NumLock',
'ScrollLock',
'SymbolLock'
];
function isModifierLock(key) {
return modifierLocks.includes(key);
}
class KeyboardHost {
isKeyPressed(keyDef) {
return !!this.pressed[String(keyDef.code)];
}
getPressedKeys() {
return Object.values(this.pressed).map((p)=>p.keyDef);
}
/** Press a key */ async keydown(instance, keyDef) {
var // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
_this_pressed, _code, _this_pressed_code;
const key = String(keyDef.key);
const code = String(keyDef.code);
const target = getActiveElement.getActiveElementOrBody(instance.config.document);
this.setKeydownTarget(target);
var _;
(_ = (_this_pressed = this.pressed)[_code = code]) !== null && _ !== void 0 ? _ : _this_pressed[_code] = {
keyDef,
unpreventedDefault: false
};
if (isModifierKey(key)) {
this.modifiers[key] = true;
}
const unprevented = instance.dispatchUIEvent(target, 'keydown', {
key,
code
});
if (isModifierLock(key) && !this.modifiers[key]) {
this.modifiers[key] = true;
this.modifierLockStart[key] = true;
}
(_this_pressed_code = this.pressed[code]).unpreventedDefault || (_this_pressed_code.unpreventedDefault = unprevented);
if (unprevented && this.hasKeyPress(key)) {
instance.dispatchUIEvent(getActiveElement.getActiveElementOrBody(instance.config.document), 'keypress', {
key,
code,
charCode: keyDef.key === 'Enter' ? 13 : String(keyDef.key).charCodeAt(0)
});
}
}
/** Release a key */ async keyup(instance, keyDef) {
const key = String(keyDef.key);
const code = String(keyDef.code);
const unprevented = this.pressed[code].unpreventedDefault;
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete this.pressed[code];
if (isModifierKey(key) && !Object.values(this.pressed).find((p)=>p.keyDef.key === key)) {
this.modifiers[key] = false;
}
instance.dispatchUIEvent(getActiveElement.getActiveElementOrBody(instance.config.document), 'keyup', {
key,
code
}, !unprevented);
if (isModifierLock(key) && this.modifiers[key]) {
if (this.modifierLockStart[key]) {
this.modifierLockStart[key] = false;
} else {
this.modifiers[key] = false;
}
}
}
setKeydownTarget(target) {
if (target !== this.lastKeydownTarget) {
this.carryChar = '';
}
this.lastKeydownTarget = target;
}
hasKeyPress(key) {
return (key.length === 1 || key === 'Enter') && !this.modifiers.Control && !this.modifiers.Alt;
}
constructor(system){
_define_property(this, "system", void 0);
_define_property(this, "modifiers", {
Alt: false,
AltGraph: false,
CapsLock: false,
Control: false,
Fn: false,
FnLock: false,
Meta: false,
NumLock: false,
ScrollLock: false,
Shift: false,
Symbol: false,
SymbolLock: false
});
_define_property(this, "pressed", {});
_define_property(this, "carryChar", '');
_define_property(this, "lastKeydownTarget", undefined);
_define_property(this, "modifierLockStart", {});
this.system = system;
}
}
exports.KeyboardHost = KeyboardHost;

View File

@@ -0,0 +1,84 @@
'use strict';
function _define_property(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
class Buttons {
getButtons() {
let v = 0;
for (const button of Object.keys(this.pressed)){
// eslint-disable-next-line no-bitwise
v |= 2 ** Number(button);
}
return v;
}
down(keyDef) {
const button = getMouseButtonId(keyDef.button);
if (button in this.pressed) {
this.pressed[button].push(keyDef);
return undefined;
}
this.pressed[button] = [
keyDef
];
return button;
}
up(keyDef) {
const button = getMouseButtonId(keyDef.button);
if (button in this.pressed) {
this.pressed[button] = this.pressed[button].filter((k)=>k.name !== keyDef.name);
if (this.pressed[button].length === 0) {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete this.pressed[button];
return button;
}
}
return undefined;
}
constructor(){
_define_property(this, "pressed", {});
}
}
const MouseButton = {
primary: 0,
secondary: 1,
auxiliary: 2,
back: 3,
X1: 3,
forward: 4,
X2: 4
};
function getMouseButtonId(button = 0) {
if (button in MouseButton) {
return MouseButton[button];
}
return Number(button);
}
// On the `MouseEvent.button` property auxiliary and secondary button are flipped compared to `MouseEvent.buttons`.
const MouseButtonFlip = {
1: 2,
2: 1
};
function getMouseEventButton(button) {
button = getMouseButtonId(button);
if (button in MouseButtonFlip) {
return MouseButtonFlip[button];
}
return button;
}
exports.Buttons = Buttons;
exports.MouseButton = MouseButton;
exports.MouseButtonFlip = MouseButtonFlip;
exports.getMouseButtonId = getMouseButtonId;
exports.getMouseEventButton = getMouseEventButton;

View File

@@ -0,0 +1,34 @@
'use strict';
function _define_property(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
class Device {
get countPressed() {
return this.pressedKeys.size;
}
isPressed(keyDef) {
return this.pressedKeys.has(keyDef.name);
}
addPressed(keyDef) {
return this.pressedKeys.add(keyDef.name);
}
removePressed(keyDef) {
return this.pressedKeys.delete(keyDef.name);
}
constructor(){
_define_property(this, "pressedKeys", new Set());
}
}
exports.Device = Device;

View File

@@ -0,0 +1,164 @@
'use strict';
var buttons = require('./buttons.js');
var device = require('./device.js');
var mouse = require('./mouse.js');
var pointer = require('./pointer.js');
function _define_property(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
class PointerHost {
isKeyPressed(keyDef) {
return this.devices.get(keyDef.pointerType).isPressed(keyDef);
}
async press(instance, keyDef, position) {
const pointerName = this.getPointerName(keyDef);
const pointer = keyDef.pointerType === 'touch' ? this.pointers.new(pointerName, keyDef).init(instance, position) : this.pointers.get(pointerName);
// TODO: deprecate the following implicit setting of position
pointer.position = position;
if (pointer.pointerType !== 'touch') {
this.mouse.position = position;
}
this.devices.get(keyDef.pointerType).addPressed(keyDef);
this.buttons.down(keyDef);
pointer.down(instance, keyDef);
if (pointer.pointerType !== 'touch' && !pointer.isPrevented) {
this.mouse.down(instance, keyDef, pointer);
}
}
async move(instance, pointerName, position) {
const pointer = this.pointers.get(pointerName);
// In (some?) browsers this order of events can be observed.
// This interweaving of events is probably unnecessary.
// While the order of mouse (or pointer) events is defined per spec,
// the order in which they interweave/follow on a user interaction depends on the implementation.
const pointermove = pointer.move(instance, position);
const mousemove = pointer.pointerType === 'touch' || pointer.isPrevented && pointer.isDown ? undefined : this.mouse.move(instance, position);
pointermove === null || pointermove === void 0 ? void 0 : pointermove.leave();
mousemove === null || mousemove === void 0 ? void 0 : mousemove.leave();
pointermove === null || pointermove === void 0 ? void 0 : pointermove.enter();
mousemove === null || mousemove === void 0 ? void 0 : mousemove.enter();
pointermove === null || pointermove === void 0 ? void 0 : pointermove.move();
mousemove === null || mousemove === void 0 ? void 0 : mousemove.move();
}
async release(instance, keyDef, position) {
const device = this.devices.get(keyDef.pointerType);
device.removePressed(keyDef);
this.buttons.up(keyDef);
const pointer = this.pointers.get(this.getPointerName(keyDef));
// TODO: deprecate the following implicit setting of position
pointer.position = position;
if (pointer.pointerType !== 'touch') {
this.mouse.position = position;
}
if (device.countPressed === 0) {
pointer.up(instance, keyDef);
}
if (pointer.pointerType === 'touch') {
pointer.release(instance);
}
if (!pointer.isPrevented) {
if (pointer.pointerType === 'touch' && !pointer.isMultitouch) {
const mousemove = this.mouse.move(instance, pointer.position);
mousemove === null || mousemove === void 0 ? void 0 : mousemove.leave();
mousemove === null || mousemove === void 0 ? void 0 : mousemove.enter();
mousemove === null || mousemove === void 0 ? void 0 : mousemove.move();
this.mouse.down(instance, keyDef, pointer);
}
if (!pointer.isMultitouch) {
const mousemove = this.mouse.move(instance, pointer.position);
mousemove === null || mousemove === void 0 ? void 0 : mousemove.leave();
mousemove === null || mousemove === void 0 ? void 0 : mousemove.enter();
mousemove === null || mousemove === void 0 ? void 0 : mousemove.move();
this.mouse.up(instance, keyDef, pointer);
}
}
}
getPointerName(keyDef) {
return keyDef.pointerType === 'touch' ? keyDef.name : keyDef.pointerType;
}
getPreviousPosition(pointerName) {
return this.pointers.has(pointerName) ? this.pointers.get(pointerName).position : undefined;
}
resetClickCount() {
this.mouse.resetClickCount();
}
getMouseTarget(instance) {
var _this_mouse_position_target;
return (_this_mouse_position_target = this.mouse.position.target) !== null && _this_mouse_position_target !== void 0 ? _this_mouse_position_target : instance.config.document.body;
}
setMousePosition(position) {
this.mouse.position = position;
this.pointers.get('mouse').position = position;
}
constructor(system){
_define_property(this, "system", void 0);
_define_property(this, "mouse", void 0);
_define_property(this, "buttons", void 0);
_define_property(this, "devices", new class {
get(k) {
var // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
_this_registry, _k;
var _;
(_ = (_this_registry = this.registry)[_k = k]) !== null && _ !== void 0 ? _ : _this_registry[_k] = new device.Device();
return this.registry[k];
}
constructor(){
_define_property(this, "registry", {});
}
}());
_define_property(this, "pointers", new class {
new(pointerName, keyDef) {
const isPrimary = keyDef.pointerType !== 'touch' || !Object.values(this.registry).some((p)=>p.pointerType === 'touch' && !p.isCancelled);
if (!isPrimary) {
Object.values(this.registry).forEach((p)=>{
if (p.pointerType === keyDef.pointerType && !p.isCancelled) {
p.isMultitouch = true;
}
});
}
this.registry[pointerName] = new pointer.Pointer({
pointerId: this.nextId++,
pointerType: keyDef.pointerType,
isPrimary
});
return this.registry[pointerName];
}
get(pointerName) {
if (!this.has(pointerName)) {
throw new Error(`Trying to access pointer "${pointerName}" which does not exist.`);
}
return this.registry[pointerName];
}
has(pointerName) {
return pointerName in this.registry;
}
constructor(){
_define_property(this, "registry", {
mouse: new pointer.Pointer({
pointerId: 1,
pointerType: 'mouse',
isPrimary: true
})
});
_define_property(this, "nextId", 2);
}
}());
this.system = system;
this.buttons = new buttons.Buttons();
this.mouse = new mouse.Mouse();
}
}
exports.PointerHost = PointerHost;

View File

@@ -0,0 +1,212 @@
'use strict';
require('../../event/behavior/click.js');
require('../../event/behavior/cut.js');
require('../../event/behavior/keydown.js');
require('../../event/behavior/keypress.js');
require('../../event/behavior/keyup.js');
require('../../event/behavior/paste.js');
require('@testing-library/dom');
require('../../utils/click/isClickableInput.js');
require('../../utils/dataTransfer/Clipboard.js');
require('../../utils/edit/isEditable.js');
require('../../utils/edit/maxLength.js');
var isDisabled = require('../../utils/misc/isDisabled.js');
require('../../utils/keyDef/readNextDescriptor.js');
var getTreeDiff = require('../../utils/misc/getTreeDiff.js');
require('../../utils/misc/level.js');
require('../../options.js');
var focus = require('../../event/focus.js');
var setSelectionPerMouse = require('../../event/selection/setSelectionPerMouse.js');
var modifySelectionPerMouse = require('../../event/selection/modifySelectionPerMouse.js');
var buttons = require('./buttons.js');
var shared = require('./shared.js');
function _define_property(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
/**
* This object is the single "virtual" mouse that might be controlled by multiple different pointer devices.
*/ class Mouse {
move(instance, position) {
const prevPosition = this.position;
const prevTarget = this.getTarget(instance);
this.position = position;
if (!shared.isDifferentPointerPosition(prevPosition, position)) {
return;
}
const nextTarget = this.getTarget(instance);
const init = this.getEventInit('mousemove');
const [leave, enter] = getTreeDiff.getTreeDiff(prevTarget, nextTarget);
return {
leave: ()=>{
if (prevTarget !== nextTarget) {
instance.dispatchUIEvent(prevTarget, 'mouseout', init);
leave.forEach((el)=>instance.dispatchUIEvent(el, 'mouseleave', init));
}
},
enter: ()=>{
if (prevTarget !== nextTarget) {
instance.dispatchUIEvent(nextTarget, 'mouseover', init);
enter.forEach((el)=>instance.dispatchUIEvent(el, 'mouseenter', init));
}
},
move: ()=>{
instance.dispatchUIEvent(nextTarget, 'mousemove', init);
this.modifySelecting(instance);
}
};
}
down(instance, keyDef, pointer) {
const button = this.buttons.down(keyDef);
if (button === undefined) {
return;
}
const target = this.getTarget(instance);
this.buttonDownTarget[button] = target;
const disabled = isDisabled.isDisabled(target);
const init = this.getEventInit('mousedown', keyDef.button);
if (disabled || instance.dispatchUIEvent(target, 'mousedown', init)) {
this.startSelecting(instance, init.detail);
focus.focusElement(target);
}
if (!disabled && buttons.getMouseEventButton(keyDef.button) === 2) {
instance.dispatchUIEvent(target, 'contextmenu', this.getEventInit('contextmenu', keyDef.button, pointer));
}
}
up(instance, keyDef, pointer) {
const button = this.buttons.up(keyDef);
if (button === undefined) {
return;
}
const target = this.getTarget(instance);
if (!isDisabled.isDisabled(target)) {
instance.dispatchUIEvent(target, 'mouseup', this.getEventInit('mouseup', keyDef.button));
this.endSelecting();
const clickTarget = getTreeDiff.getTreeDiff(this.buttonDownTarget[button], target)[2][0];
if (clickTarget) {
const init = this.getEventInit('click', keyDef.button, pointer);
if (init.detail) {
instance.dispatchUIEvent(clickTarget, init.button === 0 ? 'click' : 'auxclick', init);
if (init.button === 0 && init.detail === 2) {
instance.dispatchUIEvent(clickTarget, 'dblclick', {
...this.getEventInit('dblclick', keyDef.button),
detail: init.detail
});
}
}
}
}
}
resetClickCount() {
this.clickCount.reset();
}
getEventInit(type, button, pointer) {
const init = {
...this.position.coords
};
if (pointer) {
init.pointerId = pointer.pointerId;
init.pointerType = pointer.pointerType;
init.isPrimary = pointer.isPrimary;
}
init.button = buttons.getMouseEventButton(button);
init.buttons = this.buttons.getButtons();
if (type === 'mousedown') {
init.detail = this.clickCount.getOnDown(init.button);
} else if (type === 'mouseup') {
init.detail = this.clickCount.getOnUp(init.button);
} else if (type === 'click' || type === 'auxclick') {
init.detail = this.clickCount.incOnClick(init.button);
}
return init;
}
getTarget(instance) {
var _this_position_target;
return (_this_position_target = this.position.target) !== null && _this_position_target !== void 0 ? _this_position_target : instance.config.document.body;
}
startSelecting(instance, clickCount) {
var _this_position_caret, _this_position_caret1;
// TODO: support extending range (shift)
this.selecting = setSelectionPerMouse.setSelectionPerMouseDown({
document: instance.config.document,
target: this.getTarget(instance),
node: (_this_position_caret = this.position.caret) === null || _this_position_caret === void 0 ? void 0 : _this_position_caret.node,
offset: (_this_position_caret1 = this.position.caret) === null || _this_position_caret1 === void 0 ? void 0 : _this_position_caret1.offset,
clickCount
});
}
modifySelecting(instance) {
var _this_position_caret, _this_position_caret1;
if (!this.selecting) {
return;
}
modifySelectionPerMouse.modifySelectionPerMouseMove(this.selecting, {
document: instance.config.document,
target: this.getTarget(instance),
node: (_this_position_caret = this.position.caret) === null || _this_position_caret === void 0 ? void 0 : _this_position_caret.node,
offset: (_this_position_caret1 = this.position.caret) === null || _this_position_caret1 === void 0 ? void 0 : _this_position_caret1.offset
});
}
endSelecting() {
this.selecting = undefined;
}
constructor(){
_define_property(this, "position", {});
_define_property(this, "buttons", new buttons.Buttons());
_define_property(this, "selecting", void 0);
_define_property(this, "buttonDownTarget", {});
// According to spec the `detail` on click events should be the number
// of *consecutive* clicks with a specific button.
// On `mousedown` and `mouseup` it should be this number increased by one.
// But the browsers don't implement it this way.
// If another button is pressed,
// in Webkit: the `mouseup` on the previously pressed button has `detail: 0` and no `click`/`auxclick`.
// in Gecko: the `mouseup` and click events have the same detail as the `mousedown`.
// If there is a delay while a button is pressed,
// the `mouseup` and `click` are normal, but a following `mousedown` starts a new click count.
// We'll follow the minimal implementation of Webkit.
_define_property(this, "clickCount", new class {
incOnClick(button) {
const current = this.down[button] === undefined ? undefined : Number(this.down[button]) + 1;
this.count = this.count[button] === undefined ? {} : {
[button]: Number(this.count[button]) + 1
};
return current;
}
getOnDown(button) {
var _this_count_button;
this.down = {
[button]: (_this_count_button = this.count[button]) !== null && _this_count_button !== void 0 ? _this_count_button : 0
};
var _this_count_button1;
this.count = {
[button]: (_this_count_button1 = this.count[button]) !== null && _this_count_button1 !== void 0 ? _this_count_button1 : 0
};
return Number(this.count[button]) + 1;
}
getOnUp(button) {
return this.down[button] === undefined ? undefined : Number(this.down[button]) + 1;
}
reset() {
this.count = {};
}
constructor(){
_define_property(this, "down", {});
_define_property(this, "count", {});
}
}());
}
}
exports.Mouse = Mouse;

View File

@@ -0,0 +1,126 @@
'use strict';
require('../../utils/click/isClickableInput.js');
require('../../utils/dataTransfer/Clipboard.js');
require('../../utils/edit/isEditable.js');
require('../../utils/edit/maxLength.js');
require('../../utils/keyDef/readNextDescriptor.js');
var getTreeDiff = require('../../utils/misc/getTreeDiff.js');
require('../../utils/misc/level.js');
var cssPointerEvents = require('../../utils/pointer/cssPointerEvents.js');
var shared = require('./shared.js');
function _define_property(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
class Pointer {
init(instance, position) {
this.position = position;
const target = this.getTarget(instance);
const [, enter] = getTreeDiff.getTreeDiff(null, target);
const init = this.getEventInit();
cssPointerEvents.assertPointerEvents(instance, target);
instance.dispatchUIEvent(target, 'pointerover', init);
enter.forEach((el)=>instance.dispatchUIEvent(el, 'pointerenter', init));
return this;
}
move(instance, position) {
const prevPosition = this.position;
const prevTarget = this.getTarget(instance);
this.position = position;
if (!shared.isDifferentPointerPosition(prevPosition, position)) {
return;
}
const nextTarget = this.getTarget(instance);
const init = this.getEventInit();
const [leave, enter] = getTreeDiff.getTreeDiff(prevTarget, nextTarget);
return {
leave: ()=>{
if (cssPointerEvents.hasPointerEvents(instance, prevTarget)) {
if (prevTarget !== nextTarget) {
instance.dispatchUIEvent(prevTarget, 'pointerout', init);
leave.forEach((el)=>instance.dispatchUIEvent(el, 'pointerleave', init));
}
}
},
enter: ()=>{
cssPointerEvents.assertPointerEvents(instance, nextTarget);
if (prevTarget !== nextTarget) {
instance.dispatchUIEvent(nextTarget, 'pointerover', init);
enter.forEach((el)=>instance.dispatchUIEvent(el, 'pointerenter', init));
}
},
move: ()=>{
instance.dispatchUIEvent(nextTarget, 'pointermove', init);
}
};
}
down(instance, _keyDef) {
if (this.isDown) {
return;
}
const target = this.getTarget(instance);
cssPointerEvents.assertPointerEvents(instance, target);
this.isDown = true;
this.isPrevented = !instance.dispatchUIEvent(target, 'pointerdown', this.getEventInit());
}
up(instance, _keyDef) {
if (!this.isDown) {
return;
}
const target = this.getTarget(instance);
cssPointerEvents.assertPointerEvents(instance, target);
this.isDown = false;
instance.dispatchUIEvent(target, 'pointerup', this.getEventInit());
}
release(instance) {
const target = this.getTarget(instance);
const [leave] = getTreeDiff.getTreeDiff(target, null);
const init = this.getEventInit();
// Currently there is no PointerEventsCheckLevel that would
// make this check not use the *asserted* cached value from `up`.
/* istanbul ignore else */ if (cssPointerEvents.hasPointerEvents(instance, target)) {
instance.dispatchUIEvent(target, 'pointerout', init);
leave.forEach((el)=>instance.dispatchUIEvent(el, 'pointerleave', init));
}
this.isCancelled = true;
}
getTarget(instance) {
var _this_position_target;
return (_this_position_target = this.position.target) !== null && _this_position_target !== void 0 ? _this_position_target : instance.config.document.body;
}
getEventInit() {
return {
...this.position.coords,
pointerId: this.pointerId,
pointerType: this.pointerType,
isPrimary: this.isPrimary
};
}
constructor({ pointerId, pointerType, isPrimary }){
_define_property(this, "pointerId", void 0);
_define_property(this, "pointerType", void 0);
_define_property(this, "isPrimary", void 0);
_define_property(this, "isMultitouch", false);
_define_property(this, "isCancelled", false);
_define_property(this, "isDown", false);
_define_property(this, "isPrevented", false);
_define_property(this, "position", {});
this.pointerId = pointerId;
this.pointerType = pointerType;
this.isPrimary = isPrimary;
this.isMultitouch = !isPrimary;
}
}
exports.Pointer = Pointer;

View File

@@ -0,0 +1,8 @@
'use strict';
function isDifferentPointerPosition(positionA, positionB) {
var _positionA_coords, _positionB_coords, _positionA_coords1, _positionB_coords1, _positionA_caret, _positionB_caret, _positionA_caret1, _positionB_caret1;
return positionA.target !== positionB.target || ((_positionA_coords = positionA.coords) === null || _positionA_coords === void 0 ? void 0 : _positionA_coords.x) !== ((_positionB_coords = positionB.coords) === null || _positionB_coords === void 0 ? void 0 : _positionB_coords.y) || ((_positionA_coords1 = positionA.coords) === null || _positionA_coords1 === void 0 ? void 0 : _positionA_coords1.y) !== ((_positionB_coords1 = positionB.coords) === null || _positionB_coords1 === void 0 ? void 0 : _positionB_coords1.y) || ((_positionA_caret = positionA.caret) === null || _positionA_caret === void 0 ? void 0 : _positionA_caret.node) !== ((_positionB_caret = positionB.caret) === null || _positionB_caret === void 0 ? void 0 : _positionB_caret.node) || ((_positionA_caret1 = positionA.caret) === null || _positionA_caret1 === void 0 ? void 0 : _positionA_caret1.offset) !== ((_positionB_caret1 = positionB.caret) === null || _positionB_caret1 === void 0 ? void 0 : _positionB_caret1.offset);
}
exports.isDifferentPointerPosition = isDifferentPointerPosition;

View File

@@ -0,0 +1,37 @@
'use strict';
require('../event/behavior/click.js');
require('../event/behavior/cut.js');
require('../event/behavior/keydown.js');
require('../event/behavior/keypress.js');
require('../event/behavior/keyup.js');
require('../event/behavior/paste.js');
require('@testing-library/dom');
require('../utils/click/isClickableInput.js');
require('../utils/dataTransfer/Clipboard.js');
var isEditable = require('../utils/edit/isEditable.js');
require('../utils/edit/maxLength.js');
var isDisabled = require('../utils/misc/isDisabled.js');
require('../utils/keyDef/readNextDescriptor.js');
require('../utils/misc/level.js');
require('../options.js');
var focus = require('../event/focus.js');
var input = require('../event/input.js');
var selectAll = require('../event/selection/selectAll.js');
async function clear(element) {
if (!isEditable.isEditable(element) || isDisabled.isDisabled(element)) {
throw new Error('clear()` is only supported on editable elements.');
}
focus.focusElement(element);
if (element.ownerDocument.activeElement !== element) {
throw new Error('The element to be cleared could not be focused.');
}
selectAll.selectAll(element);
if (!selectAll.isAllSelected(element)) {
throw new Error('The element content to be cleared could not be selected.');
}
input.input(this, element, '', 'deleteContentBackward');
}
exports.clear = clear;

View File

@@ -0,0 +1,14 @@
'use strict';
var clear = require('./clear.js');
var selectOptions = require('./selectOptions.js');
var type = require('./type.js');
var upload = require('./upload.js');
exports.clear = clear.clear;
exports.deselectOptions = selectOptions.deselectOptions;
exports.selectOptions = selectOptions.selectOptions;
exports.type = type.type;
exports.upload = upload.upload;

View File

@@ -0,0 +1,119 @@
'use strict';
var dom = require('@testing-library/dom');
require('../utils/click/isClickableInput.js');
require('../utils/dataTransfer/Clipboard.js');
require('../utils/edit/isEditable.js');
require('../utils/edit/maxLength.js');
var isElementType = require('../utils/misc/isElementType.js');
var isDisabled = require('../utils/misc/isDisabled.js');
require('../utils/keyDef/readNextDescriptor.js');
require('../utils/misc/level.js');
var wait = require('../utils/misc/wait.js');
var cssPointerEvents = require('../utils/pointer/cssPointerEvents.js');
require('../event/behavior/click.js');
require('../event/behavior/cut.js');
require('../event/behavior/keydown.js');
require('../event/behavior/keypress.js');
require('../event/behavior/keyup.js');
require('../event/behavior/paste.js');
var focus = require('../event/focus.js');
async function selectOptions(select, values) {
return selectOptionsBase.call(this, true, select, values);
}
async function deselectOptions(select, values) {
return selectOptionsBase.call(this, false, select, values);
}
async function selectOptionsBase(newValue, select, values) {
if (!newValue && !select.multiple) {
throw dom.getConfig().getElementError(`Unable to deselect an option in a non-multiple select. Use selectOptions to change the selection instead.`, select);
}
const valArray = Array.isArray(values) ? values : [
values
];
const allOptions = Array.from(select.querySelectorAll('option, [role="option"]'));
const selectedOptions = valArray.map((val)=>{
if (typeof val !== 'string' && allOptions.includes(val)) {
return val;
} else {
const matchingOption = allOptions.find((o)=>o.value === val || o.innerHTML === val);
if (matchingOption) {
return matchingOption;
} else {
throw dom.getConfig().getElementError(`Value "${String(val)}" not found in options`, select);
}
}
}).filter((option)=>!isDisabled.isDisabled(option));
if (isDisabled.isDisabled(select) || !selectedOptions.length) return;
const selectOption = (option)=>{
option.selected = newValue;
this.dispatchUIEvent(select, 'input', {
bubbles: true,
cancelable: false,
composed: true
});
this.dispatchUIEvent(select, 'change');
};
if (isElementType.isElementType(select, 'select')) {
if (select.multiple) {
for (const option of selectedOptions){
const withPointerEvents = this.config.pointerEventsCheck === 0 ? true : cssPointerEvents.hasPointerEvents(this, option);
// events fired for multiple select are weird. Can't use hover...
if (withPointerEvents) {
this.dispatchUIEvent(option, 'pointerover');
this.dispatchUIEvent(select, 'pointerenter');
this.dispatchUIEvent(option, 'mouseover');
this.dispatchUIEvent(select, 'mouseenter');
this.dispatchUIEvent(option, 'pointermove');
this.dispatchUIEvent(option, 'mousemove');
this.dispatchUIEvent(option, 'pointerdown');
this.dispatchUIEvent(option, 'mousedown');
}
focus.focusElement(select);
if (withPointerEvents) {
this.dispatchUIEvent(option, 'pointerup');
this.dispatchUIEvent(option, 'mouseup');
}
selectOption(option);
if (withPointerEvents) {
this.dispatchUIEvent(option, 'click');
}
await wait.wait(this.config);
}
} else if (selectedOptions.length === 1) {
const withPointerEvents = this.config.pointerEventsCheck === 0 ? true : cssPointerEvents.hasPointerEvents(this, select);
// the click to open the select options
if (withPointerEvents) {
await this.click(select);
} else {
focus.focusElement(select);
}
selectOption(selectedOptions[0]);
if (withPointerEvents) {
// the browser triggers another click event on the select for the click on the option
// this second click has no 'down' phase
this.dispatchUIEvent(select, 'pointerover');
this.dispatchUIEvent(select, 'pointerenter');
this.dispatchUIEvent(select, 'mouseover');
this.dispatchUIEvent(select, 'mouseenter');
this.dispatchUIEvent(select, 'pointerup');
this.dispatchUIEvent(select, 'mouseup');
this.dispatchUIEvent(select, 'click');
}
await wait.wait(this.config);
} else {
throw dom.getConfig().getElementError(`Cannot select multiple options on a non-multiple select`, select);
}
} else if (select.getAttribute('role') === 'listbox') {
for (const option of selectedOptions){
await this.click(option);
await this.unhover(option);
}
} else {
throw dom.getConfig().getElementError(`Cannot select options on elements that are neither select nor listbox elements`, select);
}
}
exports.deselectOptions = deselectOptions;
exports.selectOptions = selectOptions;

View File

@@ -0,0 +1,29 @@
'use strict';
var index = require('../keyboard/index.js');
require('../utils/click/isClickableInput.js');
require('../utils/dataTransfer/Clipboard.js');
require('../utils/edit/isEditable.js');
require('../utils/edit/maxLength.js');
require('../utils/keyDef/readNextDescriptor.js');
require('../utils/misc/level.js');
require('../options.js');
var setSelectionRange = require('../event/selection/setSelectionRange.js');
async function type(element, text, { skipClick = this.config.skipClick, skipAutoClose = this.config.skipAutoClose, initialSelectionStart, initialSelectionEnd } = {}) {
// TODO: properly type guard
// we use this workaround for now to prevent changing behavior
if (element.disabled) return;
if (!skipClick) {
await this.click(element);
}
if (initialSelectionStart !== undefined) {
setSelectionRange.setSelectionRange(element, initialSelectionStart, initialSelectionEnd !== null && initialSelectionEnd !== void 0 ? initialSelectionEnd : initialSelectionStart);
}
await this.keyboard(text);
if (!skipAutoClose) {
await index.releaseAllKeys(this);
}
}
exports.type = type;

View File

@@ -0,0 +1,64 @@
'use strict';
require('../utils/click/isClickableInput.js');
var FileList = require('../utils/dataTransfer/FileList.js');
require('../utils/dataTransfer/Clipboard.js');
require('../utils/edit/isEditable.js');
require('../utils/edit/maxLength.js');
var setFiles = require('../utils/edit/setFiles.js');
var isElementType = require('../utils/misc/isElementType.js');
var isDisabled = require('../utils/misc/isDisabled.js');
var getWindow = require('../utils/misc/getWindow.js');
require('../utils/keyDef/readNextDescriptor.js');
require('../utils/misc/level.js');
require('../options.js');
async function upload(element, fileOrFiles) {
const input = isElementType.isElementType(element, 'label') ? element.control : element;
if (!input || !isElementType.isElementType(input, 'input', {
type: 'file'
})) {
throw new TypeError(`The ${input === element ? 'given' : 'associated'} ${input === null || input === void 0 ? void 0 : input.tagName} element does not accept file uploads`);
}
if (isDisabled.isDisabled(element)) return;
const files = (Array.isArray(fileOrFiles) ? fileOrFiles : [
fileOrFiles
]).filter((file)=>!this.config.applyAccept || isAcceptableFile(file, input.accept)).slice(0, input.multiple ? undefined : 1);
const fileDialog = ()=>{
var _input_files;
// do not fire an input event if the file selection does not change
if (files.length === ((_input_files = input.files) === null || _input_files === void 0 ? void 0 : _input_files.length) && files.every((f, i)=>{
var _input_files;
return f === ((_input_files = input.files) === null || _input_files === void 0 ? void 0 : _input_files.item(i));
})) {
return;
}
setFiles.setFiles(input, FileList.createFileList(getWindow.getWindow(element), files));
this.dispatchUIEvent(input, 'input');
this.dispatchUIEvent(input, 'change');
};
input.addEventListener('fileDialog', fileDialog);
await this.click(element);
input.removeEventListener('fileDialog', fileDialog);
}
function isAcceptableFile(file, accept) {
if (!accept) {
return true;
}
const wildcards = [
'audio/*',
'image/*',
'video/*'
];
return accept.split(',').some((acceptToken)=>{
if (acceptToken.startsWith('.')) {
// tokens starting with a dot represent a file extension
return file.name.endsWith(acceptToken);
} else if (wildcards.includes(acceptToken)) {
return file.type.startsWith(acceptToken.substr(0, acceptToken.length - 1));
}
return file.type === acceptToken;
});
}
exports.upload = upload;

View File

@@ -0,0 +1,20 @@
'use strict';
var isElementType = require('../misc/isElementType.js');
var clickableInputTypes;
(function(clickableInputTypes) {
clickableInputTypes["button"] = "button";
clickableInputTypes["color"] = "color";
clickableInputTypes["file"] = "file";
clickableInputTypes["image"] = "image";
clickableInputTypes["reset"] = "reset";
clickableInputTypes["submit"] = "submit";
clickableInputTypes["checkbox"] = "checkbox";
clickableInputTypes["radio"] = "radio";
})(clickableInputTypes || (clickableInputTypes = {}));
function isClickableInput(element) {
return isElementType.isElementType(element, 'button') || isElementType.isElementType(element, 'input') && element.type in clickableInputTypes;
}
exports.isClickableInput = isClickableInput;

View File

@@ -0,0 +1,16 @@
'use strict';
// jsdom does not implement Blob.text()
function readBlobText(blob, FileReader) {
return new Promise((res, rej)=>{
const fr = new FileReader();
fr.onerror = rej;
fr.onabort = rej;
fr.onload = ()=>{
res(String(fr.result));
};
fr.readAsText(blob);
});
}
exports.readBlobText = readBlobText;

View File

@@ -0,0 +1,170 @@
'use strict';
var getWindow = require('../misc/getWindow.js');
var Blob = require('./Blob.js');
var DataTransfer = require('./DataTransfer.js');
// Clipboard is not available in jsdom
function _define_property(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
// MDN lists string|Blob|Promise<Blob|string> as possible types in ClipboardItemData
// lib.dom.d.ts lists only Promise<Blob|string>
// https://developer.mozilla.org/en-US/docs/Web/API/ClipboardItem/ClipboardItem#syntax
function createClipboardItem(window, ...blobs) {
const dataMap = Object.fromEntries(blobs.map((b)=>[
typeof b === 'string' ? 'text/plain' : b.type,
Promise.resolve(b)
]));
// use real ClipboardItem if available
/* istanbul ignore if */ if (typeof window.ClipboardItem !== 'undefined') {
return new window.ClipboardItem(dataMap);
}
return new class ClipboardItem {
get types() {
return Array.from(Object.keys(this.data));
}
async getType(type) {
const value = await this.data[type];
if (!value) {
throw new Error(`${type} is not one of the available MIME types on this item.`);
}
return value instanceof window.Blob ? value : new window.Blob([
value
], {
type
});
}
constructor(d){
_define_property(this, "data", void 0);
this.data = d;
}
}(dataMap);
}
const ClipboardStubControl = Symbol('Manage ClipboardSub');
function createClipboardStub(window, control) {
return Object.assign(new class Clipboard extends window.EventTarget {
async read() {
return Array.from(this.items);
}
async readText() {
let text = '';
for (const item of this.items){
const type = item.types.includes('text/plain') ? 'text/plain' : item.types.find((t)=>t.startsWith('text/'));
if (type) {
text += await item.getType(type).then((b)=>Blob.readBlobText(b, window.FileReader));
}
}
return text;
}
async write(data) {
this.items = data;
}
async writeText(text) {
this.items = [
createClipboardItem(window, text)
];
}
constructor(...args){
super(...args);
_define_property(this, "items", []);
}
}(), {
[ClipboardStubControl]: control
});
}
function isClipboardStub(clipboard) {
return !!(clipboard === null || clipboard === void 0 ? void 0 : clipboard[ClipboardStubControl]);
}
function attachClipboardStubToView(window) {
if (isClipboardStub(window.navigator.clipboard)) {
return window.navigator.clipboard[ClipboardStubControl];
}
const realClipboard = Object.getOwnPropertyDescriptor(window.navigator, 'clipboard');
let stub;
const control = {
resetClipboardStub: ()=>{
stub = createClipboardStub(window, control);
},
detachClipboardStub: ()=>{
/* istanbul ignore if */ if (realClipboard) {
Object.defineProperty(window.navigator, 'clipboard', realClipboard);
} else {
Object.defineProperty(window.navigator, 'clipboard', {
value: undefined,
configurable: true
});
}
}
};
stub = createClipboardStub(window, control);
Object.defineProperty(window.navigator, 'clipboard', {
get: ()=>stub,
configurable: true
});
return stub[ClipboardStubControl];
}
function resetClipboardStubOnView(window) {
if (isClipboardStub(window.navigator.clipboard)) {
window.navigator.clipboard[ClipboardStubControl].resetClipboardStub();
}
}
function detachClipboardStubFromView(window) {
if (isClipboardStub(window.navigator.clipboard)) {
window.navigator.clipboard[ClipboardStubControl].detachClipboardStub();
}
}
async function readDataTransferFromClipboard(document) {
const window = document.defaultView;
const clipboard = window === null || window === void 0 ? void 0 : window.navigator.clipboard;
const items = clipboard && await clipboard.read();
if (!items) {
throw new Error('The Clipboard API is unavailable.');
}
const dt = DataTransfer.createDataTransfer(window);
for (const item of items){
for (const type of item.types){
dt.setData(type, await item.getType(type).then((b)=>Blob.readBlobText(b, window.FileReader)));
}
}
return dt;
}
async function writeDataTransferToClipboard(document, clipboardData) {
const window = getWindow.getWindow(document);
const clipboard = window.navigator.clipboard;
const items = [];
for(let i = 0; i < clipboardData.items.length; i++){
const dtItem = clipboardData.items[i];
const blob = DataTransfer.getBlobFromDataTransferItem(window, dtItem);
items.push(createClipboardItem(window, blob));
}
const written = clipboard && await clipboard.write(items).then(()=>true, // Can happen with other implementations that e.g. require permissions
/* istanbul ignore next */ ()=>false);
if (!written) {
throw new Error('The Clipboard API is unavailable.');
}
}
const g = globalThis;
/* istanbul ignore else */ if (typeof g.afterEach === 'function') {
g.afterEach(()=>resetClipboardStubOnView(globalThis.window));
}
/* istanbul ignore else */ if (typeof g.afterAll === 'function') {
g.afterAll(()=>detachClipboardStubFromView(globalThis.window));
}
exports.attachClipboardStubToView = attachClipboardStubToView;
exports.createClipboardItem = createClipboardItem;
exports.detachClipboardStubFromView = detachClipboardStubFromView;
exports.readDataTransferFromClipboard = readDataTransferFromClipboard;
exports.resetClipboardStubOnView = resetClipboardStubOnView;
exports.writeDataTransferToClipboard = writeDataTransferToClipboard;

View File

@@ -0,0 +1,140 @@
'use strict';
var FileList = require('./FileList.js');
function _define_property(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
// DataTransfer is not implemented in jsdom.
// DataTransfer with FileList is being created by the browser on certain events.
class DataTransferItemStub {
getAsFile() {
return this.file;
}
getAsString(callback) {
if (typeof this.data === 'string') {
callback(this.data);
}
}
/* istanbul ignore next */ webkitGetAsEntry() {
throw new Error('not implemented');
}
constructor(dataOrFile, type){
_define_property(this, "kind", void 0);
_define_property(this, "type", void 0);
_define_property(this, "file", null);
_define_property(this, "data", undefined);
if (typeof dataOrFile === 'string') {
this.kind = 'string';
this.type = String(type);
this.data = dataOrFile;
} else {
this.kind = 'file';
this.type = dataOrFile.type;
this.file = dataOrFile;
}
}
}
class DataTransferItemListStub extends Array {
add(...args) {
const item = new DataTransferItemStub(args[0], args[1]);
this.push(item);
return item;
}
clear() {
this.splice(0, this.length);
}
remove(index) {
this.splice(index, 1);
}
}
function getTypeMatcher(type, exact) {
const [group, sub] = type.split('/');
const isGroup = !sub || sub === '*';
return (item)=>{
return exact ? item.type === (isGroup ? group : type) : isGroup ? item.type.startsWith(`${group}/`) : item.type === group;
};
}
function createDataTransferStub(window) {
return new class DataTransferStub {
getData(format) {
var _this_items_find;
const match = (_this_items_find = this.items.find(getTypeMatcher(format, true))) !== null && _this_items_find !== void 0 ? _this_items_find : this.items.find(getTypeMatcher(format, false));
let text = '';
match === null || match === void 0 ? void 0 : match.getAsString((t)=>{
text = t;
});
return text;
}
setData(format, data) {
const matchIndex = this.items.findIndex(getTypeMatcher(format, true));
const item = new DataTransferItemStub(data, format);
if (matchIndex >= 0) {
this.items.splice(matchIndex, 1, item);
} else {
this.items.push(item);
}
}
clearData(format) {
if (format) {
const matchIndex = this.items.findIndex(getTypeMatcher(format, true));
if (matchIndex >= 0) {
this.items.remove(matchIndex);
}
} else {
this.items.clear();
}
}
get types() {
const t = [];
if (this.files.length) {
t.push('Files');
}
this.items.forEach((i)=>t.push(i.type));
Object.freeze(t);
return t;
}
/* istanbul ignore next */ setDragImage() {}
constructor(){
_define_property(this, "dropEffect", 'none');
_define_property(this, "effectAllowed", 'uninitialized');
_define_property(this, "items", new DataTransferItemListStub());
_define_property(this, "files", FileList.createFileList(window, []));
}
}();
}
function createDataTransfer(window, files = []) {
// Use real DataTransfer if available
const dt = typeof window.DataTransfer === 'undefined' ? createDataTransferStub(window) : /* istanbul ignore next */ new window.DataTransfer();
Object.defineProperty(dt, 'files', {
get: ()=>FileList.createFileList(window, files)
});
return dt;
}
function getBlobFromDataTransferItem(window, item) {
if (item.kind === 'file') {
return item.getAsFile();
}
let data = '';
item.getAsString((s)=>{
data = s;
});
return new window.Blob([
data
], {
type: item.type
});
}
exports.createDataTransfer = createDataTransfer;
exports.getBlobFromDataTransferItem = getBlobFromDataTransferItem;

View File

@@ -0,0 +1,24 @@
'use strict';
// FileList can not be created per constructor.
function createFileList(window, files) {
const list = {
...files,
length: files.length,
item: (index)=>list[index],
[Symbol.iterator]: function* nextFile() {
for(let i = 0; i < list.length; i++){
yield list[i];
}
}
};
list.constructor = window.FileList;
// guard for environments without FileList
/* istanbul ignore else */ if (window.FileList) {
Object.setPrototypeOf(list, window.FileList.prototype);
}
Object.freeze(list);
return list;
}
exports.createFileList = createFileList;

View File

@@ -0,0 +1,18 @@
'use strict';
//jsdom is not supporting isContentEditable
function isContentEditable(element) {
return element.hasAttribute('contenteditable') && (element.getAttribute('contenteditable') == 'true' || element.getAttribute('contenteditable') == '');
}
/**
* If a node is a contenteditable or inside one, return that element.
*/ function getContentEditable(node) {
const element = getElement(node);
return element && (element.closest('[contenteditable=""]') || element.closest('[contenteditable="true"]'));
}
function getElement(node) {
return node.nodeType === 1 ? node : node.parentElement;
}
exports.getContentEditable = getContentEditable;
exports.isContentEditable = isContentEditable;

View File

@@ -0,0 +1,29 @@
'use strict';
var isElementType = require('../misc/isElementType.js');
var isContentEditable = require('./isContentEditable.js');
function isEditable(element) {
return isEditableInputOrTextArea(element) && !element.readOnly || isContentEditable.isContentEditable(element);
}
var editableInputTypes;
(function(editableInputTypes) {
editableInputTypes["text"] = "text";
editableInputTypes["date"] = "date";
editableInputTypes["datetime-local"] = "datetime-local";
editableInputTypes["email"] = "email";
editableInputTypes["month"] = "month";
editableInputTypes["number"] = "number";
editableInputTypes["password"] = "password";
editableInputTypes["search"] = "search";
editableInputTypes["tel"] = "tel";
editableInputTypes["time"] = "time";
editableInputTypes["url"] = "url";
editableInputTypes["week"] = "week";
})(editableInputTypes || (editableInputTypes = {}));
function isEditableInputOrTextArea(element) {
return isElementType.isElementType(element, 'textarea') || isElementType.isElementType(element, 'input') && element.type in editableInputTypes;
}
exports.isEditable = isEditable;
exports.isEditableInputOrTextArea = isEditableInputOrTextArea;

View File

@@ -0,0 +1,26 @@
'use strict';
var isElementType = require('../misc/isElementType.js');
var maxLengthSupportedTypes;
(function(maxLengthSupportedTypes) {
maxLengthSupportedTypes["email"] = "email";
maxLengthSupportedTypes["password"] = "password";
maxLengthSupportedTypes["search"] = "search";
maxLengthSupportedTypes["telephone"] = "telephone";
maxLengthSupportedTypes["text"] = "text";
maxLengthSupportedTypes["url"] = "url";
})(maxLengthSupportedTypes || (maxLengthSupportedTypes = {}));
// can't use .maxLength property because of a jsdom bug:
// https://github.com/jsdom/jsdom/issues/2927
function getMaxLength(element) {
var _element_getAttribute;
const attr = (_element_getAttribute = element.getAttribute('maxlength')) !== null && _element_getAttribute !== void 0 ? _element_getAttribute : '';
return /^\d+$/.test(attr) && Number(attr) >= 0 ? Number(attr) : undefined;
}
function supportsMaxLength(element) {
return isElementType.isElementType(element, 'textarea') || isElementType.isElementType(element, 'input') && element.type in maxLengthSupportedTypes;
}
exports.getMaxLength = getMaxLength;
exports.supportsMaxLength = supportsMaxLength;

View File

@@ -0,0 +1,59 @@
'use strict';
// It is not possible to create a real FileList programmatically.
// Therefore assigning `files` property with a programmatically created FileList results in an error.
// Just assigning the property (as per fireEvent) breaks the interweaving with the `value` property.
const fakeFiles = Symbol('files and value properties are mocked');
function restoreProperty(obj, prop, descriptor) {
if (descriptor) {
Object.defineProperty(obj, prop, descriptor);
} else {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete obj[prop];
}
}
function setFiles(el, files) {
var _el_fakeFiles;
(_el_fakeFiles = el[fakeFiles]) === null || _el_fakeFiles === void 0 ? void 0 : _el_fakeFiles.restore();
const typeDescr = Object.getOwnPropertyDescriptor(el, 'type');
const valueDescr = Object.getOwnPropertyDescriptor(el, 'value');
const filesDescr = Object.getOwnPropertyDescriptor(el, 'files');
function restore() {
restoreProperty(el, 'type', typeDescr);
restoreProperty(el, 'value', valueDescr);
restoreProperty(el, 'files', filesDescr);
}
el[fakeFiles] = {
restore
};
Object.defineProperties(el, {
files: {
configurable: true,
get: ()=>files
},
value: {
configurable: true,
get: ()=>files.length ? `C:\\fakepath\\${files[0].name}` : '',
set (v) {
if (v === '') {
restore();
} else {
var _valueDescr_set;
valueDescr === null || valueDescr === void 0 ? void 0 : (_valueDescr_set = valueDescr.set) === null || _valueDescr_set === void 0 ? void 0 : _valueDescr_set.call(el, v);
}
}
},
type: {
configurable: true,
get: ()=>'file',
set (v) {
if (v !== 'file') {
restore();
el.type = v;
}
}
}
});
}
exports.setFiles = setFiles;

View File

@@ -0,0 +1,40 @@
'use strict';
const parseInt = globalThis.parseInt;
function buildTimeValue(value) {
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 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')}`;
}
function isValidDateOrTimeValue(element, value) {
const clone = element.cloneNode();
clone.value = value;
return clone.value === value;
}
exports.buildTimeValue = buildTimeValue;
exports.isValidDateOrTimeValue = isValidDateOrTimeValue;

View File

@@ -0,0 +1,126 @@
'use strict';
var isContentEditable = require('../edit/isContentEditable.js');
var isElementType = require('../misc/isElementType.js');
function getNextCursorPosition(node, offset, direction, inputType) {
// The behavior at text node zero offset is inconsistent.
// When walking backwards:
// Firefox always moves to zero offset and jumps over last offset.
// Chrome jumps over zero offset per default but over last offset when Shift is pressed.
// The cursor always moves to zero offset if the focus area (contenteditable or body) ends there.
// When walking foward both ignore zero offset.
// When walking over input elements the cursor moves before or after that element.
// When walking over line breaks the cursor moves inside any following text node.
if (isTextNode(node) && offset + direction >= 0 && offset + direction <= node.nodeValue.length) {
return {
node,
offset: offset + direction
};
}
const nextNode = getNextCharacterContentNode(node, offset, direction);
if (nextNode) {
if (isTextNode(nextNode)) {
return {
node: nextNode,
offset: direction > 0 ? Math.min(1, nextNode.nodeValue.length) : Math.max(nextNode.nodeValue.length - 1, 0)
};
} else if (isElementType.isElementType(nextNode, 'br')) {
const nextPlusOne = getNextCharacterContentNode(nextNode, undefined, direction);
if (!nextPlusOne) {
// The behavior when there is no possible cursor position beyond the line break is inconsistent.
// In Chrome outside of contenteditable moving before a leading line break is possible.
// A leading line break can still be removed per deleteContentBackward.
// A trailing line break on the other hand is not removed by deleteContentForward.
if (direction < 0 && inputType === 'deleteContentBackward') {
return {
node: nextNode.parentNode,
offset: getOffset(nextNode)
};
}
return undefined;
} else if (isTextNode(nextPlusOne)) {
return {
node: nextPlusOne,
offset: direction > 0 ? 0 : nextPlusOne.nodeValue.length
};
} else if (direction < 0 && isElementType.isElementType(nextPlusOne, 'br')) {
return {
node: nextNode.parentNode,
offset: getOffset(nextNode)
};
} else {
return {
node: nextPlusOne.parentNode,
offset: getOffset(nextPlusOne) + (direction > 0 ? 0 : 1)
};
}
} else {
return {
node: nextNode.parentNode,
offset: getOffset(nextNode) + (direction > 0 ? 1 : 0)
};
}
}
}
function getNextCharacterContentNode(node, offset, direction) {
const nextOffset = Number(offset) + (direction < 0 ? -1 : 0);
if (offset !== undefined && isElement(node) && nextOffset >= 0 && nextOffset < node.children.length) {
node = node.children[nextOffset];
}
return walkNodes(node, direction === 1 ? 'next' : 'previous', isTreatedAsCharacterContent);
}
function isTreatedAsCharacterContent(node) {
if (isTextNode(node)) {
return true;
}
if (isElement(node)) {
if (isElementType.isElementType(node, [
'input',
'textarea'
])) {
return node.type !== 'hidden';
} else if (isElementType.isElementType(node, 'br')) {
return true;
}
}
return false;
}
function getOffset(node) {
let i = 0;
while(node.previousSibling){
i++;
node = node.previousSibling;
}
return i;
}
function isElement(node) {
return node.nodeType === 1;
}
function isTextNode(node) {
return node.nodeType === 3;
}
function walkNodes(node, direction, callback) {
for(;;){
var _node_ownerDocument;
const sibling = node[`${direction}Sibling`];
if (sibling) {
node = getDescendant(sibling, direction === 'next' ? 'first' : 'last');
if (callback(node)) {
return node;
}
} else if (node.parentNode && (!isElement(node.parentNode) || !isContentEditable.isContentEditable(node.parentNode) && node.parentNode !== ((_node_ownerDocument = node.ownerDocument) === null || _node_ownerDocument === void 0 ? void 0 : _node_ownerDocument.body))) {
node = node.parentNode;
} else {
break;
}
}
}
function getDescendant(node, direction) {
while(node.hasChildNodes()){
node = node[`${direction}Child`];
}
return node;
}
exports.getNextCursorPosition = getNextCursorPosition;

View File

@@ -0,0 +1,23 @@
'use strict';
var isDisabled = require('../misc/isDisabled.js');
function getActiveElement(document) {
const activeElement = document.activeElement;
if (activeElement === null || activeElement === void 0 ? void 0 : activeElement.shadowRoot) {
return getActiveElement(activeElement.shadowRoot);
} else {
// Browser does not yield disabled elements as document.activeElement - jsdom does
if (isDisabled.isDisabled(activeElement)) {
return document.ownerDocument ? /* istanbul ignore next */ document.ownerDocument.body : document.body;
}
return activeElement;
}
}
function getActiveElementOrBody(document) {
var _getActiveElement;
return (_getActiveElement = getActiveElement(document)) !== null && _getActiveElement !== void 0 ? _getActiveElement : /* istanbul ignore next */ document.body;
}
exports.getActiveElement = getActiveElement;
exports.getActiveElementOrBody = getActiveElementOrBody;

View File

@@ -0,0 +1,80 @@
'use strict';
var isDisabled = require('../misc/isDisabled.js');
var isElementType = require('../misc/isElementType.js');
var isVisible = require('../misc/isVisible.js');
var selector = require('./selector.js');
function getTabDestination(activeElement, shift) {
const document = activeElement.ownerDocument;
const focusableElements = document.querySelectorAll(selector.FOCUSABLE_SELECTOR);
const enabledElements = Array.from(focusableElements).filter((el)=>el === activeElement || !(Number(el.getAttribute('tabindex')) < 0 || isDisabled.isDisabled(el)));
// tabindex has no effect if the active element has negative tabindex
if (Number(activeElement.getAttribute('tabindex')) >= 0) {
enabledElements.sort((a, b)=>{
const i = Number(a.getAttribute('tabindex'));
const j = Number(b.getAttribute('tabindex'));
if (i === j) {
return 0;
} else if (i === 0) {
return 1;
} else if (j === 0) {
return -1;
}
return i - j;
});
}
const checkedRadio = {};
let prunedElements = [
document.body
];
const activeRadioGroup = isElementType.isElementType(activeElement, 'input', {
type: 'radio'
}) ? activeElement.name : undefined;
enabledElements.forEach((currentElement)=>{
const el = currentElement;
// For radio groups keep only the active radio
// If there is no active radio, keep only the checked radio
// If there is no checked radio, treat like everything else
if (isElementType.isElementType(el, 'input', {
type: 'radio'
}) && el.name) {
// If the active element is part of the group, add only that
if (el === activeElement) {
prunedElements.push(el);
return;
} else if (el.name === activeRadioGroup) {
return;
}
// If we stumble upon a checked radio, remove the others
if (el.checked) {
prunedElements = prunedElements.filter((e)=>!isElementType.isElementType(e, 'input', {
type: 'radio',
name: el.name
}));
prunedElements.push(el);
checkedRadio[el.name] = el;
return;
}
// If we already found the checked one, skip
if (typeof checkedRadio[el.name] !== 'undefined') {
return;
}
}
prunedElements.push(el);
});
for(let index = prunedElements.findIndex((el)=>el === activeElement);;){
index += shift ? -1 : 1;
// loop at overflow
if (index === prunedElements.length) {
index = 0;
} else if (index === -1) {
index = prunedElements.length - 1;
}
if (prunedElements[index] === activeElement || prunedElements[index] === document.body || isVisible.isVisible(prunedElements[index])) {
return prunedElements[index];
}
}
}
exports.getTabDestination = getTabDestination;

View File

@@ -0,0 +1,9 @@
'use strict';
var selector = require('./selector.js');
function isFocusable(element) {
return element.matches(selector.FOCUSABLE_SELECTOR);
}
exports.isFocusable = isFocusable;

View File

@@ -0,0 +1,20 @@
'use strict';
var isClickableInput = require('../click/isClickableInput.js');
var isEditable = require('../edit/isEditable.js');
/**
* Determine if the element has its own selection implementation
* and does not interact with the Document Selection API.
*/ function hasOwnSelection(node) {
return isElement(node) && isEditable.isEditableInputOrTextArea(node);
}
function hasNoSelection(node) {
return isElement(node) && isClickableInput.isClickableInput(node);
}
function isElement(node) {
return node.nodeType === 1;
}
exports.hasNoSelection = hasNoSelection;
exports.hasOwnSelection = hasOwnSelection;

View File

@@ -0,0 +1,14 @@
'use strict';
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;

View File

@@ -0,0 +1,81 @@
'use strict';
var isClickableInput = require('./click/isClickableInput.js');
var Blob = require('./dataTransfer/Blob.js');
var DataTransfer = require('./dataTransfer/DataTransfer.js');
var FileList = require('./dataTransfer/FileList.js');
var Clipboard = require('./dataTransfer/Clipboard.js');
var timeValue = require('./edit/timeValue.js');
var isContentEditable = require('./edit/isContentEditable.js');
var isEditable = require('./edit/isEditable.js');
var maxLength = require('./edit/maxLength.js');
var setFiles = require('./edit/setFiles.js');
var cursor = require('./focus/cursor.js');
var getActiveElement = require('./focus/getActiveElement.js');
var getTabDestination = require('./focus/getTabDestination.js');
var isFocusable = require('./focus/isFocusable.js');
var selection = require('./focus/selection.js');
var selector = require('./focus/selector.js');
var readNextDescriptor = require('./keyDef/readNextDescriptor.js');
var cloneEvent = require('./misc/cloneEvent.js');
var findClosest = require('./misc/findClosest.js');
var getDocumentFromNode = require('./misc/getDocumentFromNode.js');
var getTreeDiff = require('./misc/getTreeDiff.js');
var getWindow = require('./misc/getWindow.js');
var isDescendantOrSelf = require('./misc/isDescendantOrSelf.js');
var isElementType = require('./misc/isElementType.js');
var isVisible = require('./misc/isVisible.js');
var isDisabled = require('./misc/isDisabled.js');
var level = require('./misc/level.js');
var wait = require('./misc/wait.js');
var cssPointerEvents = require('./pointer/cssPointerEvents.js');
exports.isClickableInput = isClickableInput.isClickableInput;
exports.readBlobText = Blob.readBlobText;
exports.createDataTransfer = DataTransfer.createDataTransfer;
exports.getBlobFromDataTransferItem = DataTransfer.getBlobFromDataTransferItem;
exports.createFileList = FileList.createFileList;
exports.attachClipboardStubToView = Clipboard.attachClipboardStubToView;
exports.createClipboardItem = Clipboard.createClipboardItem;
exports.detachClipboardStubFromView = Clipboard.detachClipboardStubFromView;
exports.readDataTransferFromClipboard = Clipboard.readDataTransferFromClipboard;
exports.resetClipboardStubOnView = Clipboard.resetClipboardStubOnView;
exports.writeDataTransferToClipboard = Clipboard.writeDataTransferToClipboard;
exports.buildTimeValue = timeValue.buildTimeValue;
exports.isValidDateOrTimeValue = timeValue.isValidDateOrTimeValue;
exports.getContentEditable = isContentEditable.getContentEditable;
exports.isContentEditable = isContentEditable.isContentEditable;
exports.isEditable = isEditable.isEditable;
exports.isEditableInputOrTextArea = isEditable.isEditableInputOrTextArea;
exports.getMaxLength = maxLength.getMaxLength;
exports.supportsMaxLength = maxLength.supportsMaxLength;
exports.setFiles = setFiles.setFiles;
exports.getNextCursorPosition = cursor.getNextCursorPosition;
exports.getActiveElement = getActiveElement.getActiveElement;
exports.getActiveElementOrBody = getActiveElement.getActiveElementOrBody;
exports.getTabDestination = getTabDestination.getTabDestination;
exports.isFocusable = isFocusable.isFocusable;
exports.hasNoSelection = selection.hasNoSelection;
exports.hasOwnSelection = selection.hasOwnSelection;
exports.FOCUSABLE_SELECTOR = selector.FOCUSABLE_SELECTOR;
exports.readNextDescriptor = readNextDescriptor.readNextDescriptor;
exports.cloneEvent = cloneEvent.cloneEvent;
exports.findClosest = findClosest.findClosest;
exports.getDocumentFromNode = getDocumentFromNode.getDocumentFromNode;
exports.getTreeDiff = getTreeDiff.getTreeDiff;
exports.getWindow = getWindow.getWindow;
exports.isDescendantOrSelf = isDescendantOrSelf.isDescendantOrSelf;
exports.isElementType = isElementType.isElementType;
exports.isVisible = isVisible.isVisible;
exports.isDisabled = isDisabled.isDisabled;
Object.defineProperty(exports, "ApiLevel", {
enumerable: true,
get: function () { return level.ApiLevel; }
});
exports.getLevelRef = level.getLevelRef;
exports.setLevelRef = level.setLevelRef;
exports.wait = wait.wait;
exports.assertPointerEvents = cssPointerEvents.assertPointerEvents;
exports.hasPointerEvents = cssPointerEvents.hasPointerEvents;

View File

@@ -0,0 +1,92 @@
'use strict';
var bracketDict;
(function(bracketDict) {
bracketDict["{"] = "}";
bracketDict["["] = "]";
})(bracketDict || (bracketDict = {}));
/**
* Read the next key definition from user input
*
* Describe key per `{descriptor}` or `[descriptor]`.
* Everything else will be interpreted as a single character as descriptor - e.g. `a`.
* Brackets `{` and `[` can be escaped by doubling - e.g. `foo[[bar` translates to `foo[bar`.
* A previously pressed key can be released per `{/descriptor}`.
* Keeping the key pressed can be written as `{descriptor>}`.
* When keeping the key pressed you can choose how long the key is pressed `{descriptor>3}`.
* You can then release the key per `{descriptor>3/}` or keep it pressed and continue with the next key.
*/ function readNextDescriptor(text, context) {
let pos = 0;
const startBracket = text[pos] in bracketDict ? text[pos] : '';
pos += startBracket.length;
const isEscapedChar = new RegExp(`^\\${startBracket}{2}`).test(text);
const type = isEscapedChar ? '' : startBracket;
return {
type,
...type === '' ? readPrintableChar(text, pos, context) : readTag(text, pos, type, context)
};
}
function readPrintableChar(text, pos, context) {
const descriptor = text[pos];
assertDescriptor(descriptor, text, pos, context);
pos += descriptor.length;
return {
consumedLength: pos,
descriptor,
releasePrevious: false,
releaseSelf: true,
repeat: 1
};
}
function readTag(text, pos, startBracket, context) {
var _text_slice_match, _text_slice_match1;
const releasePreviousModifier = text[pos] === '/' ? '/' : '';
pos += releasePreviousModifier.length;
const escapedDescriptor = startBracket === '{' && text[pos] === '\\';
pos += Number(escapedDescriptor);
const descriptor = escapedDescriptor ? text[pos] : (_text_slice_match = text.slice(pos).match(startBracket === '{' ? /^\w+|^[^}>/]/ : /^\w+/)) === null || _text_slice_match === void 0 ? void 0 : _text_slice_match[0];
assertDescriptor(descriptor, text, pos, context);
pos += descriptor.length;
var _text_slice_match_;
const repeatModifier = (_text_slice_match_ = (_text_slice_match1 = text.slice(pos).match(/^>\d+/)) === null || _text_slice_match1 === void 0 ? void 0 : _text_slice_match1[0]) !== null && _text_slice_match_ !== void 0 ? _text_slice_match_ : '';
pos += repeatModifier.length;
const releaseSelfModifier = text[pos] === '/' || !repeatModifier && text[pos] === '>' ? text[pos] : '';
pos += releaseSelfModifier.length;
const expectedEndBracket = bracketDict[startBracket];
const endBracket = text[pos] === expectedEndBracket ? expectedEndBracket : '';
if (!endBracket) {
throw new Error(getErrorMessage([
!repeatModifier && 'repeat modifier',
!releaseSelfModifier && 'release modifier',
`"${expectedEndBracket}"`
].filter(Boolean).join(' or '), text[pos], text, context));
}
pos += endBracket.length;
return {
consumedLength: pos,
descriptor,
releasePrevious: !!releasePreviousModifier,
repeat: repeatModifier ? Math.max(Number(repeatModifier.substr(1)), 1) : 1,
releaseSelf: hasReleaseSelf(releaseSelfModifier, repeatModifier)
};
}
function assertDescriptor(descriptor, text, pos, context) {
if (!descriptor) {
throw new Error(getErrorMessage('key descriptor', text[pos], text, context));
}
}
function hasReleaseSelf(releaseSelfModifier, repeatModifier) {
if (releaseSelfModifier) {
return releaseSelfModifier === '/';
}
if (repeatModifier) {
return false;
}
}
function getErrorMessage(expected, found, text, context) {
return `Expected ${expected} but found "${found !== null && found !== void 0 ? found : ''}" in "${text}"
See ${context === 'pointer' ? `https://testing-library.com/docs/user-event/pointer#pressing-a-button-or-touching-the-screen` : `https://testing-library.com/docs/user-event/keyboard`}
for more information about how userEvent parses your input.`;
}
exports.readNextDescriptor = readNextDescriptor;

View File

@@ -0,0 +1,7 @@
'use strict';
function cloneEvent(event) {
return new event.constructor(event.type, event);
}
exports.cloneEvent = cloneEvent;

View File

@@ -0,0 +1,14 @@
'use strict';
function findClosest(element, callback) {
let el = element;
do {
if (callback(el)) {
return el;
}
el = el.parentElement;
}while (el && el !== element.ownerDocument.body)
return undefined;
}
exports.findClosest = findClosest;

View File

@@ -0,0 +1,10 @@
'use strict';
function getDocumentFromNode(el) {
return isDocument(el) ? el : el.ownerDocument;
}
function isDocument(node) {
return node.nodeType === 9;
}
exports.getDocumentFromNode = getDocumentFromNode;

View File

@@ -0,0 +1,25 @@
'use strict';
function getTreeDiff(a, b) {
const treeA = [];
for(let el = a; el; el = el.parentElement){
treeA.push(el);
}
const treeB = [];
for(let el = b; el; el = el.parentElement){
treeB.push(el);
}
let i = 0;
for(;; i++){
if (i >= treeA.length || i >= treeB.length || treeA[treeA.length - 1 - i] !== treeB[treeB.length - 1 - i]) {
break;
}
}
return [
treeA.slice(0, treeA.length - i),
treeB.slice(0, treeB.length - i),
treeB.slice(treeB.length - i)
];
}
exports.getTreeDiff = getTreeDiff;

View File

@@ -0,0 +1,19 @@
'use strict';
function getWindow(node) {
var _node_ownerDocument;
if (isDocument(node) && node.defaultView) {
return node.defaultView;
} else if ((_node_ownerDocument = node.ownerDocument) === null || _node_ownerDocument === void 0 ? void 0 : _node_ownerDocument.defaultView) {
return node.ownerDocument.defaultView;
}
throw new Error(`Could not determine window of node. Node was ${describe(node)}`);
}
function isDocument(node) {
return node.nodeType === 9;
}
function describe(val) {
return typeof val === 'function' ? `function ${val.name}` : val === null ? 'null' : String(val);
}
exports.getWindow = getWindow;

View File

@@ -0,0 +1,14 @@
'use strict';
function isDescendantOrSelf(potentialDescendant, potentialAncestor) {
let el = potentialDescendant;
do {
if (el === potentialAncestor) {
return true;
}
el = el.parentElement;
}while (el)
return false;
}
exports.isDescendantOrSelf = isDescendantOrSelf;

View File

@@ -0,0 +1,33 @@
'use strict';
var isElementType = require('./isElementType.js');
// This should probably just rely on the :disabled pseudo-class, but JSDOM doesn't implement it properly.
function isDisabled(element) {
for(let el = element; el; el = el.parentElement){
if (isElementType.isElementType(el, [
'button',
'input',
'select',
'textarea',
'optgroup',
'option'
])) {
if (el.hasAttribute('disabled')) {
return true;
}
} else if (isElementType.isElementType(el, 'fieldset')) {
var _el_querySelector;
if (el.hasAttribute('disabled') && !((_el_querySelector = el.querySelector(':scope > legend')) === null || _el_querySelector === void 0 ? void 0 : _el_querySelector.contains(element))) {
return true;
}
} else if (el.tagName.includes('-')) {
if (el.constructor.formAssociated && el.hasAttribute('disabled')) {
return true;
}
}
}
return false;
}
exports.isDisabled = isDisabled;

View File

@@ -0,0 +1,20 @@
'use strict';
function isElementType(element, tag, props) {
if (element.namespaceURI && element.namespaceURI !== 'http://www.w3.org/1999/xhtml') {
return false;
}
tag = Array.isArray(tag) ? tag : [
tag
];
// tagName is uppercase in HTMLDocument and lowercase in XMLDocument
if (!tag.includes(element.tagName.toLowerCase())) {
return false;
}
if (props) {
return Object.entries(props).every(([k, v])=>element[k] === v);
}
return true;
}
exports.isElementType = isElementType;

View File

@@ -0,0 +1,19 @@
'use strict';
var getWindow = require('./getWindow.js');
function isVisible(element) {
const window = getWindow.getWindow(element);
for(let el = element; el === null || el === void 0 ? void 0 : el.ownerDocument; el = el.parentElement){
const { display, visibility } = window.getComputedStyle(el);
if (display === 'none') {
return false;
}
if (visibility === 'hidden') {
return false;
}
}
return true;
}
exports.isVisible = isVisible;

Some files were not shown because too many files have changed in this diff Show More