Set up comprehensive frontend testing infrastructure
- Install Jest for unit testing with React Testing Library - Install Playwright for end-to-end testing - Configure Jest with proper TypeScript support and module mapping - Create test setup files and utilities for both unit and e2e tests Components: * Jest configuration with coverage thresholds * Playwright configuration with browser automation * Unit tests for LoginForm, AuthContext, and useSocketIO hook * E2E tests for authentication, dashboard, and agents workflows * GitHub Actions workflow for automated testing * Mock data and API utilities for consistent testing * Test documentation with best practices Testing features: - Unit tests with 70% coverage threshold - E2E tests with API mocking and user journey testing - CI/CD integration for automated test runs - Cross-browser testing support with Playwright - Authentication system testing end-to-end 🚀 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
18
frontend/node_modules/@testing-library/user-event/dist/cjs/event/selection/getInputRange.js
generated
vendored
Normal file
18
frontend/node_modules/@testing-library/user-event/dist/cjs/event/selection/getInputRange.js
generated
vendored
Normal 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 === undefined ? undefined : _typeAndSelection_selection.getRangeAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
exports.getInputRange = getInputRange;
|
||||
31
frontend/node_modules/@testing-library/user-event/dist/cjs/event/selection/getTargetTypeAndSelection.js
generated
vendored
Normal file
31
frontend/node_modules/@testing-library/user-event/dist/cjs/event/selection/getTargetTypeAndSelection.js
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
'use strict';
|
||||
|
||||
var UI = require('../../document/UI.js');
|
||||
require('../../utils/dataTransfer/Clipboard.js');
|
||||
var isContentEditable = require('../../utils/edit/isContentEditable.js');
|
||||
var selection = require('../../utils/focus/selection.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 === undefined ? undefined : 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 === undefined ? undefined : 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;
|
||||
24
frontend/node_modules/@testing-library/user-event/dist/cjs/event/selection/index.js
generated
vendored
Normal file
24
frontend/node_modules/@testing-library/user-event/dist/cjs/event/selection/index.js
generated
vendored
Normal 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;
|
||||
21
frontend/node_modules/@testing-library/user-event/dist/cjs/event/selection/modifySelection.js
generated
vendored
Normal file
21
frontend/node_modules/@testing-library/user-event/dist/cjs/event/selection/modifySelection.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
var UI = require('../../document/UI.js');
|
||||
require('../../utils/dataTransfer/Clipboard.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 === undefined ? undefined : (_focusNode_ownerDocument_getSelection = _focusNode_ownerDocument.getSelection()) === null || _focusNode_ownerDocument_getSelection === undefined ? undefined : _focusNode_ownerDocument_getSelection.extend(focusNode, focusOffset);
|
||||
}
|
||||
|
||||
exports.modifySelection = modifySelection;
|
||||
40
frontend/node_modules/@testing-library/user-event/dist/cjs/event/selection/modifySelectionPerMouse.js
generated
vendored
Normal file
40
frontend/node_modules/@testing-library/user-event/dist/cjs/event/selection/modifySelectionPerMouse.js
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
'use strict';
|
||||
|
||||
var UI = require('../../document/UI.js');
|
||||
require('../../utils/dataTransfer/Clipboard.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 === undefined ? undefined : selection.removeAllRanges();
|
||||
selection === null || selection === undefined ? undefined : selection.addRange(range.cloneRange());
|
||||
}
|
||||
}
|
||||
|
||||
exports.modifySelectionPerMouseMove = modifySelectionPerMouseMove;
|
||||
38
frontend/node_modules/@testing-library/user-event/dist/cjs/event/selection/moveSelection.js
generated
vendored
Normal file
38
frontend/node_modules/@testing-library/user-event/dist/cjs/event/selection/moveSelection.js
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
'use strict';
|
||||
|
||||
var UI = require('../../document/UI.js');
|
||||
require('../../utils/dataTransfer/Clipboard.js');
|
||||
var cursor = require('../../utils/focus/cursor.js');
|
||||
var selection = require('../../utils/focus/selection.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 === undefined ? undefined : 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;
|
||||
61
frontend/node_modules/@testing-library/user-event/dist/cjs/event/selection/resolveCaretPosition.js
generated
vendored
Normal file
61
frontend/node_modules/@testing-library/user-event/dist/cjs/event/selection/resolveCaretPosition.js
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
'use strict';
|
||||
|
||||
var UI = require('../../document/UI.js');
|
||||
require('../../utils/dataTransfer/Clipboard.js');
|
||||
var selection = require('../../utils/focus/selection.js');
|
||||
|
||||
function resolveCaretPosition({ target, node, offset }) {
|
||||
if (selection.hasOwnSelection(target)) {
|
||||
return {
|
||||
node: target,
|
||||
offset: offset !== null && offset !== undefined ? offset : UI.getUIValue(target).length
|
||||
};
|
||||
} else if (node) {
|
||||
return {
|
||||
node,
|
||||
offset: offset !== null && offset !== undefined ? 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 !== undefined ? offset : c.nodeValue.length
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
i += step;
|
||||
}
|
||||
return {
|
||||
node,
|
||||
offset: node.childNodes.length
|
||||
};
|
||||
}
|
||||
|
||||
exports.resolveCaretPosition = resolveCaretPosition;
|
||||
38
frontend/node_modules/@testing-library/user-event/dist/cjs/event/selection/selectAll.js
generated
vendored
Normal file
38
frontend/node_modules/@testing-library/user-event/dist/cjs/event/selection/selectAll.js
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
'use strict';
|
||||
|
||||
var UI = require('../../document/UI.js');
|
||||
require('../../utils/dataTransfer/Clipboard.js');
|
||||
var isContentEditable = require('../../utils/edit/isContentEditable.js');
|
||||
var selection = require('../../utils/focus/selection.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 !== undefined ? _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 !== undefined ? _getContentEditable : target.ownerDocument.body;
|
||||
const selection$1 = target.ownerDocument.getSelection();
|
||||
return (selection$1 === null || selection$1 === undefined ? undefined : selection$1.anchorNode) === focusNode && selection$1.focusNode === focusNode && selection$1.anchorOffset === 0 && selection$1.focusOffset === focusNode.childNodes.length;
|
||||
}
|
||||
|
||||
exports.isAllSelected = isAllSelected;
|
||||
exports.selectAll = selectAll;
|
||||
21
frontend/node_modules/@testing-library/user-event/dist/cjs/event/selection/setSelection.js
generated
vendored
Normal file
21
frontend/node_modules/@testing-library/user-event/dist/cjs/event/selection/setSelection.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
var UI = require('../../document/UI.js');
|
||||
require('../../utils/dataTransfer/Clipboard.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 === undefined ? undefined : (_anchorNode_ownerDocument_getSelection = _anchorNode_ownerDocument.getSelection()) === null || _anchorNode_ownerDocument_getSelection === undefined ? undefined : _anchorNode_ownerDocument_getSelection.setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset);
|
||||
}
|
||||
|
||||
exports.setSelection = setSelection;
|
||||
81
frontend/node_modules/@testing-library/user-event/dist/cjs/event/selection/setSelectionPerMouse.js
generated
vendored
Normal file
81
frontend/node_modules/@testing-library/user-event/dist/cjs/event/selection/setSelectionPerMouse.js
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
'use strict';
|
||||
|
||||
var UI = require('../../document/UI.js');
|
||||
require('../../utils/dataTransfer/Clipboard.js');
|
||||
var selection = require('../../utils/focus/selection.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 !== undefined ? start : text.length,
|
||||
focusOffset: end !== null && end !== undefined ? end : text.length
|
||||
});
|
||||
return {
|
||||
node: target,
|
||||
start: start !== null && start !== undefined ? start : 0,
|
||||
end: end !== null && end !== undefined ? 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 === undefined ? undefined : selection.removeAllRanges();
|
||||
selection === null || selection === undefined ? undefined : 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 !== undefined ? 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;
|
||||
31
frontend/node_modules/@testing-library/user-event/dist/cjs/event/selection/setSelectionRange.js
generated
vendored
Normal file
31
frontend/node_modules/@testing-library/user-event/dist/cjs/event/selection/setSelectionRange.js
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
'use strict';
|
||||
|
||||
require('../../utils/dataTransfer/Clipboard.js');
|
||||
var isContentEditable = require('../../utils/edit/isContentEditable.js');
|
||||
var selection = require('../../utils/focus/selection.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 === undefined ? undefined : _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;
|
||||
40
frontend/node_modules/@testing-library/user-event/dist/cjs/event/selection/updateSelectionOnFocus.js
generated
vendored
Normal file
40
frontend/node_modules/@testing-library/user-event/dist/cjs/event/selection/updateSelectionOnFocus.js
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
'use strict';
|
||||
|
||||
require('../../utils/dataTransfer/Clipboard.js');
|
||||
var isContentEditable = require('../../utils/edit/isContentEditable.js');
|
||||
var selection = require('../../utils/focus/selection.js');
|
||||
|
||||
// The browser implementation seems to have changed.
|
||||
// When focus is inside <input type="text"/>,
|
||||
// Chrome updates Selection to be collapsed at the position of the input element.
|
||||
// TODO: update implementation to match that of current browsers
|
||||
/**
|
||||
* 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 === undefined ? undefined : 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 === undefined ? undefined : _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;
|
||||
Reference in New Issue
Block a user