UNPKG

@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
"use strict"; 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'); }); }); });