enzyme
Version:
JavaScript Testing utilities for React
253 lines (215 loc) • 7.32 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.SELECTOR = exports.isCompoundSelector = undefined;
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; /* eslint no-use-before-define:0 */
exports.propsOfNode = propsOfNode;
exports.typeOfNode = typeOfNode;
exports.getNode = getNode;
exports.childrenEqual = childrenEqual;
exports.nodeEqual = nodeEqual;
exports.containsChildrenSubArray = containsChildrenSubArray;
exports.propFromEvent = propFromEvent;
exports.withSetStateAllowed = withSetStateAllowed;
exports.splitSelector = splitSelector;
exports.isSimpleSelector = isSimpleSelector;
exports.selectorError = selectorError;
exports.selectorType = selectorType;
exports.AND = AND;
exports.coercePropValue = coercePropValue;
exports.mapNativeEventNames = mapNativeEventNames;
var _underscore = require('underscore');
var _reactCompat = require('./react-compat');
var _version = require('./version');
function propsOfNode(node) {
if (_version.REACT013 && node && node._store) {
return node._store.props || {};
}
if (node && node._reactInternalComponent && node._reactInternalComponent._currentElement) {
return node._reactInternalComponent._currentElement.props || {};
}
return node && node.props || {};
}
function typeOfNode(node) {
return node ? node.type : null;
}
function getNode(node) {
return (0, _reactCompat.isDOMComponent)(node) ? (0, _reactCompat.findDOMNode)(node) : node;
}
function childrenEqual(a, b) {
if (a === b) return true;
if (!Array.isArray(a) && !Array.isArray(b)) {
return nodeEqual(a, b);
}
if (!a && !b) return true;
if (a.length !== b.length) return false;
if (a.length === 0 && b.length === 0) return true;
for (var i = 0; i < a.length; i++) {
if (!nodeEqual(a[i], b[i])) return false;
}
return true;
}
function nodeEqual(a, b) {
if (a === b) return true;
if (!a || !b) return false;
if (a.type !== b.type) return false;
var left = propsOfNode(a);
var leftKeys = Object.keys(left);
var right = propsOfNode(b);
for (var i = 0; i < leftKeys.length; i++) {
var prop = leftKeys[i];
if (!(prop in right)) return false;
if (prop === 'children') {
if (!childrenEqual((0, _reactCompat.childrenToArray)(left.children), (0, _reactCompat.childrenToArray)(right.children))) {
return false;
}
} else if (right[prop] === left[prop]) {
// continue;
} else if (_typeof(right[prop]) === _typeof(left[prop]) && _typeof(left[prop]) === 'object') {
if (!(0, _underscore.isEqual)(left[prop], right[prop])) return false;
} else {
return false;
}
}
if (typeof a !== 'string' && typeof a !== 'number') {
return leftKeys.length === Object.keys(right).length;
}
return false;
}
function containsChildrenSubArray(match, node, subArray) {
var children = childrenOfNode(node);
return children.some(function (_, i) {
return arraysEqual(match, children.slice(i, subArray.length), subArray);
});
}
function arraysEqual(match, left, right) {
return left.length === right.length && left.every(function (el, i) {
return match(el, right[i]);
});
}
function childrenOfNode(node) {
var props = propsOfNode(node);
var children = props.children;
return (0, _reactCompat.childrenToArray)(children);
}
// 'click' => 'onClick'
// 'mouseEnter' => 'onMouseEnter'
function propFromEvent(event) {
var nativeEvent = mapNativeEventNames(event);
return 'on' + String(nativeEvent[0].toUpperCase()) + String(nativeEvent.substring(1));
}
function withSetStateAllowed(fn) {
// NOTE(lmr):
// this is currently here to circumvent a React bug where `setState()` is
// not allowed without global being defined.
var cleanup = false;
if (typeof global.document === 'undefined') {
cleanup = true;
global.document = {};
}
fn();
if (cleanup) {
delete global.document;
}
}
function splitSelector(selector) {
return selector.split(/(?=\.|\[.*\])/);
}
function isSimpleSelector(selector) {
// any of these characters pretty much guarantee it's a complex selector
return !/[~\s:>]/.test(selector);
}
function selectorError(selector) {
return new TypeError('Enzyme received a complex CSS selector (\'' + String(selector) + '\') that it does not currently support');
}
var isCompoundSelector = exports.isCompoundSelector = /([a-z]\.[a-z]|[a-z]\[.*\])/i;
var isPropSelector = /^\[.*\]$/;
var SELECTOR = exports.SELECTOR = {
CLASS_TYPE: 0,
ID_TYPE: 1,
PROP_TYPE: 2
};
function selectorType(selector) {
if (selector[0] === '.') {
return SELECTOR.CLASS_TYPE;
} else if (selector[0] === '#') {
return SELECTOR.ID_TYPE;
} else if (isPropSelector.test(selector)) {
return SELECTOR.PROP_TYPE;
}
}
function AND(fns) {
return function (x) {
var i = fns.length;
while (i--) {
if (!fns[i](x)) return false;
}
return true;
};
}
function coercePropValue(propName, propValue) {
// can be undefined
if (propValue === undefined) {
return propValue;
}
var trimmedValue = propValue.trim();
// if propValue includes quotes, it should be
// treated as a string
if (/^(['"]).*\1$/.test(trimmedValue)) {
return trimmedValue.slice(1, -1);
}
var numericPropValue = +trimmedValue;
// if parseInt is not NaN, then we've wanted a number
if (!isNaN(numericPropValue)) {
return numericPropValue;
}
// coerce to boolean
if (trimmedValue === 'true') return true;
if (trimmedValue === 'false') return false;
// user provided an unquoted string value
throw new TypeError('Enzyme::Unable to parse selector \'[' + String(propName) + '=' + String(propValue) + ']\'. ' + ('Perhaps you forgot to escape a string? Try \'[' + String(propName) + '="' + String(trimmedValue) + '"]\' instead.'));
}
function mapNativeEventNames(event) {
var nativeToReactEventMap = {
compositionend: 'compositionEnd',
compositionstart: 'compositionStart',
compositionupdate: 'compositionUpdate',
keydown: 'keyDown',
keyup: 'keyUp',
keypress: 'keyPress',
contextmenu: 'contextMenu',
doubleclick: 'doubleClick',
dragend: 'dragEnd',
dragenter: 'dragEnter',
dragexist: 'dragExit',
dragleave: 'dragLeave',
dragover: 'dragOver',
dragstart: 'dragStart',
mousedown: 'mouseDown',
mousemove: 'mouseMove',
mouseout: 'mouseOut',
mouseover: 'mouseOver',
mouseup: 'mouseUp',
touchcancel: 'touchCancel',
touchend: 'touchEnd',
touchmove: 'touchMove',
touchstart: 'touchStart',
canplay: 'canPlay',
canplaythrough: 'canPlayThrough',
durationchange: 'durationChange',
loadeddata: 'loadedData',
loadedmetadata: 'loadedMetadata',
loadstart: 'loadStart',
ratechange: 'rateChange',
timeupdate: 'timeUpdate',
volumechange: 'volumeChange'
};
if (_version.REACT014) {
// these could not be simulated in React 0.13:
// https://github.com/facebook/react/issues/1297
nativeToReactEventMap.mouseenter = 'mouseEnter';
nativeToReactEventMap.mouseleave = 'mouseLeave';
}
return nativeToReactEventMap[event] || event;
}