@enact/core
Version:
Enact is an open source JavaScript framework containing everything you need to create a fast, scalable mobile or web application.
476 lines (468 loc) • 19.2 kB
JavaScript
;
var _react = require("@testing-library/react");
var _propTypes = _interopRequireDefault(require("prop-types"));
var _react2 = require("react");
var _util = require("../util");
var _jsxRuntime = require("react/jsx-runtime");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
function _possibleConstructorReturn(t, e) { if (e && ("object" == typeof e || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); }
function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; }
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }
function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); }
function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }
describe('util', function () {
describe('cap', function () {
test('should return a capitalized string', function () {
expect((0, _util.cap)('abc')).toBe('Abc');
});
});
describe('clamp', function () {
test('should return a value between a min value and a max value', function () {
expect((0, _util.clamp)(10, 20, 15)).toBe(15);
expect((0, _util.clamp)(10, 20, 0)).toBe(10);
expect((0, _util.clamp)(10, 20, 30)).toBe(20);
expect((0, _util.clamp)(10, 20, 10)).toBe(10);
expect((0, _util.clamp)(10, 20, 20)).toBe(20);
expect((0, _util.clamp)(20, 10, 10)).toBe(20); // special case
});
});
describe('checkPropTypes', function () {
var TestComponent = /*#__PURE__*/function (_Component) {
function TestComponent(props) {
var _this;
_classCallCheck(this, TestComponent);
_this = _callSuper(this, TestComponent, [props]);
(0, _util.checkPropTypes)(_this, _this.props);
return _this;
}
_inherits(TestComponent, _Component);
return _createClass(TestComponent, [{
key: "render",
value: function render() {
return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
children: "Test"
});
}
}]);
}(_react2.Component);
TestComponent.displayName = 'TestComponent';
TestComponent.propTypes = {
bool: _propTypes["default"].bool,
string: _propTypes["default"].string
};
var consoleWarnMock = null;
var consoleErrorMock = null;
beforeEach(function () {
consoleWarnMock = jest.spyOn(console, 'warn').mockImplementation();
consoleErrorMock = jest.spyOn(console, 'error').mockImplementation();
});
afterEach(function () {
consoleWarnMock.mockRestore();
consoleErrorMock.mockRestore();
});
test('should not call any console.error for a correct prop', function () {
(0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(TestComponent, {
bool: true,
string: "String"
}));
expect(consoleErrorMock).not.toHaveBeenCalled();
});
test('should call console.error for a wrong prop', function () {
(0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(TestComponent, {
bool: "true",
string: "String"
}));
expect(consoleErrorMock).toHaveBeenCalled();
});
});
describe('coerceArray', function () {
test('should return an array', function () {
expect((0, _util.coerceArray)(['a'])).toEqual(['a']);
expect((0, _util.coerceArray)('a')).toEqual(['a']);
});
});
describe('coerceFunction', function () {
test('should return a function', function () {
var _coerceFunction;
expect(typeof (0, _util.coerceFunction)(function () {
return 'function';
})).toEqual('function');
expect(typeof (0, _util.coerceFunction)('value')).toEqual('function');
expect((_coerceFunction = (0, _util.coerceFunction)('value')) === null || _coerceFunction === void 0 ? void 0 : _coerceFunction()).toEqual('value');
});
});
describe('extractAriaProps', function () {
test('should extract aria-related props as a return object', function () {
var testProps = {
role: 'button',
'aria-hidden': true,
value: 'value'
};
var expected = {
role: 'button',
'aria-hidden': true
};
var remaining = {
value: 'value'
};
var actual = (0, _util.extractAriaProps)(testProps);
expect(actual).toMatchObject(expected);
expect(testProps).toMatchObject(remaining);
});
});
describe('isRenderable', function () {
test('should return {true} for function', function () {
var expected = true;
var view = (0, _util.isRenderable)(function () {});
expect(view).toEqual(expected);
});
test('should return {true} for string', function () {
var expected = true;
var view = (0, _util.isRenderable)('div');
expect(view).toEqual(expected);
});
test('should return {true} for React.forwardRef', function () {
var expected = true;
var view = (0, _util.isRenderable)(/*#__PURE__*/(0, _react2.forwardRef)(function () {}));
expect(view).toEqual(expected);
});
test('should return {true} for React.memo', function () {
var expected = true;
var view = (0, _util.isRenderable)(/*#__PURE__*/(0, _react2.memo)(function () {}));
expect(view).toEqual(expected);
});
test('should return {true} for React.lazy', function () {
var expected = true;
var view = (0, _util.isRenderable)(/*#__PURE__*/(0, _react2.lazy)(function () {}));
expect(view).toEqual(expected);
});
});
describe('memoize', function () {
test('should memoize function', function () {
var obj = {},
testMethod = function testMethod(key) {
obj[key] = (obj[key] || 0) + 1;
},
memoizedTest = (0, _util.memoize)(testMethod);
expect(obj).not.toHaveProperty('a');
memoizedTest('a');
expect(obj).toHaveProperty('a', 1);
memoizedTest('a');
memoizedTest('a');
expect(obj).toHaveProperty('a', 1);
});
test('should forward all args to memoized function', function () {
var spy = jest.fn();
var memoized = (0, _util.memoize)(spy);
memoized(1, 2);
var expected = [1, 2];
var actual = spy.mock.calls[0];
expect(expected).toEqual(actual);
});
});
describe('mergeClassNameMaps', function () {
var baseMap = {
'class-base-only': 'real-class-base-only',
'class-shared': 'real-class-shared-base',
'class-shared-another': 'real-class-shared-another-base'
};
var additiveMap = {
'class-shared': 'real-class-shared-additive',
'class-shared-another': 'real-class-shared-another-additive',
'class-additive-only': 'real-class-additive-only'
};
// Helper function to get an object from the proxy object that has only getters for properties to make testing easier
var getResultFromProxy = function getResultFromProxy(proxy) {
var keys = ['class-base-only', 'class-shared', 'class-shared-another', 'class-additive-only'];
var obj = {};
for (var i = 0; i < keys.length; i++) {
if (keys[i] !== proxy[keys[i]]) {
obj[keys[i]] = proxy[keys[i]];
}
}
return obj;
};
test('should return a base map if an additive map is not given', function () {
var actual = (0, _util.mergeClassNameMaps)(baseMap);
expect(actual).toEqual(baseMap);
});
test('should return a merged map containing shared class names', function () {
var expected = {
'class-base-only': 'real-class-base-only',
'class-shared': 'real-class-shared-base real-class-shared-additive',
'class-shared-another': 'real-class-shared-another-base real-class-shared-another-additive'
};
var actual = getResultFromProxy((0, _util.mergeClassNameMaps)(baseMap, additiveMap));
expect(actual).toEqual(expected);
});
test('should return a merged map containing allowed matching class names', function () {
var expected = {
'class-base-only': 'real-class-base-only',
'class-shared': 'real-class-shared-base real-class-shared-additive',
'class-shared-another': 'real-class-shared-another-base'
};
var actual = getResultFromProxy((0, _util.mergeClassNameMaps)(baseMap, additiveMap, ['class-shared']));
expect(actual).toEqual(expected);
});
});
describe('mapAndFilterChildren', function () {
test('Returns null if null passed', function () {
var expected = null;
var actual = (0, _util.mapAndFilterChildren)(null, function (val) {
return val;
});
expect(actual).toBe(expected);
});
test('Returns passed array if identity filter', function () {
var children = [1, 2, 3];
var expected = children;
var actual = (0, _util.mapAndFilterChildren)(children, function (val) {
return val;
});
expect(actual).toEqual(expected);
});
test('Returns passed array without nullish or false entries with identity filter', function () {
// eslint-disable-next-line no-undefined
var children = [1, 2, null, 3, undefined, false];
var expected = [1, 2, 3];
var actual = (0, _util.mapAndFilterChildren)(children, function (val) {
return val;
});
expect(actual).toEqual(expected);
});
test('Does not call filter with nullish or false entries', function () {
var spy = jest.fn();
// eslint-disable-next-line no-undefined
var children = [1, 2, null, 3, undefined, false];
(0, _util.mapAndFilterChildren)(children, spy);
var expected = 3;
var actual = spy.mock.calls.length;
expect(actual).toBe(expected);
});
test('Returns without null entries from filter', function () {
var children = [1, 2, 3];
var expected = [1, 3];
var actual = (0, _util.mapAndFilterChildren)(children, function (val) {
return val === 2 ? null : val;
});
expect(actual).toEqual(expected);
});
test('Runs custom filter', function () {
var children = [1, 2, 3];
var expected = [1];
var actual = (0, _util.mapAndFilterChildren)(children, function (val) {
return val === 2 ? null : val;
}, function (val) {
return val === 1;
});
expect(actual).toEqual(expected);
});
test('should forward value and index to callback', function () {
var spy = jest.fn();
(0, _util.mapAndFilterChildren)([1], spy);
var expected = [1,
// value
0 // index
];
var actual = spy.mock.calls[0];
expect(expected).toEqual(actual);
});
});
describe('normalizePublicClassNames', function () {
var css = {
a: 'a-class',
b: 'b-class'
};
test('should return all css keys when publicClassNames is true', function () {
expect((0, _util.normalizePublicClassNames)(true, css)).toEqual(['a', 'b']);
});
test('should split a string publicClassNames value', function () {
expect((0, _util.normalizePublicClassNames)('a b', css)).toEqual(['a', 'b']);
});
test('should return `true` unchanged when css is not provided', function () {
expect((0, _util.normalizePublicClassNames)(true)).toBe(true);
});
test('should return `false` unchanged', function () {
expect((0, _util.normalizePublicClassNames)(false, css)).toBe(false);
});
test('should return `undefined` unchanged', function () {
// eslint-disable-next-line no-undefined
expect((0, _util.normalizePublicClassNames)(undefined, css)).toBe(undefined);
});
test('should return an array value unchanged', function () {
var allowed = ['a', 'b'];
expect((0, _util.normalizePublicClassNames)(allowed, css)).toBe(allowed);
});
});
describe('applyDefaultProps', function () {
test('should return target unchanged when keys are not provided', function () {
var target = {
size: 'small'
};
expect((0, _util.applyDefaultProps)(target, {
size: 'large'
}, null)).toBe(target);
expect(target).toEqual({
size: 'small'
});
});
test('should apply defaults for keys that are `undefined`', function () {
// eslint-disable-next-line no-undefined
var target = {
size: undefined
};
(0, _util.applyDefaultProps)(target, {
size: 'large'
}, ['size']);
expect(target.size).toBe('large');
});
test('should not overwrite a key that is already set', function () {
var target = {
size: 'small'
};
(0, _util.applyDefaultProps)(target, {
size: 'large'
}, ['size']);
expect(target.size).toBe('small');
});
test('should preserve falsy-but-defined values', function () {
var target = {
count: 0,
label: '',
flag: false
};
(0, _util.applyDefaultProps)(target, {
count: 5,
label: 'default',
flag: true
}, ['count', 'label', 'flag']);
expect(target.count).toBe(0);
expect(target.label).toBe('');
expect(target.flag).toBe(false);
});
});
describe('setDefaultProps', function () {
var props = {
// eslint-disable-next-line no-undefined
direction: undefined,
index: 0,
size: 'small'
};
var defaultProps = {
direction: 'below',
selected: true,
size: 'large'
};
test('should set props that are missing or `undefined` to default values', function () {
var expected = {
direction: 'below',
index: 0,
selected: true,
size: 'small'
};
var actual = (0, _util.setDefaultProps)(props, defaultProps);
expect(expected).toEqual(actual);
});
});
describe('shallowEqual', function () {
var child = {
name: 'child'
};
test('should return `true` if the values of all keys are strictly equal', function () {
expect((0, _util.shallowEqual)(child, child)).toBe(true);
expect((0, _util.shallowEqual)(child, null)).toBe(false);
var fakeChild = {
name: 'fake'
};
expect((0, _util.shallowEqual)(child, fakeChild)).toBe(false);
fakeChild.name = 'child';
expect((0, _util.shallowEqual)(child, fakeChild)).toBe(true);
child.toString = function () {
child.toString.apply(child, arguments);
};
expect((0, _util.shallowEqual)(child, fakeChild)).toBe(false);
});
});
describe('usePrevious', function () {
test('should return the initial value on first render', function () {
var _renderHook = (0, _react.renderHook)(function () {
return (0, _util.usePrevious)(1);
}),
result = _renderHook.result;
expect(result.current).toBe(1);
});
test('should return the previous value after the value changes', function () {
var value = 1;
var _renderHook2 = (0, _react.renderHook)(function () {
return (0, _util.usePrevious)(value);
}),
result = _renderHook2.result,
rerender = _renderHook2.rerender;
// eslint-disable-next-line testing-library/no-unnecessary-act
(0, _react.act)(function () {
value = 2;
rerender();
});
expect(result.current).toBe(1);
});
test('should track the previous value across multiple changes', function () {
var value = 'a';
var _renderHook3 = (0, _react.renderHook)(function () {
return (0, _util.usePrevious)(value);
}),
result = _renderHook3.result,
rerender = _renderHook3.rerender;
// eslint-disable-next-line testing-library/no-unnecessary-act
(0, _react.act)(function () {
value = 'b';
rerender();
});
expect(result.current).toBe('a');
// eslint-disable-next-line testing-library/no-unnecessary-act
(0, _react.act)(function () {
value = 'c';
rerender();
});
expect(result.current).toBe('b');
});
test('should not update previous value when value stays the same', function () {
var value = 42;
var _renderHook4 = (0, _react.renderHook)(function () {
return (0, _util.usePrevious)(value);
}),
result = _renderHook4.result,
rerender = _renderHook4.rerender;
// eslint-disable-next-line testing-library/no-unnecessary-act
(0, _react.act)(function () {
rerender();
});
expect(result.current).toBe(42);
});
test('should keep prior value when value changes then stays the same', function () {
var value = 'a';
var _renderHook5 = (0, _react.renderHook)(function () {
return (0, _util.usePrevious)(value);
}),
result = _renderHook5.result,
rerender = _renderHook5.rerender;
// eslint-disable-next-line testing-library/no-unnecessary-act
(0, _react.act)(function () {
value = 'b';
rerender();
});
expect(result.current).toBe('a');
// eslint-disable-next-line testing-library/no-unnecessary-act
(0, _react.act)(function () {
rerender();
});
expect(result.current).toBe('a');
});
});
});