UNPKG

@enact/core

Version:

Enact is an open source JavaScript framework containing everything you need to create a fast, scalable mobile or web application.

727 lines (718 loc) 28 kB
"use strict"; var _propTypes = _interopRequireDefault(require("prop-types")); var _react = require("react"); var _react2 = require("@testing-library/react"); var _handle = require("../handle"); 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 _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); } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, 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); } describe('handle', function () { var makeEvent = function makeEvent(payload) { return _objectSpread({ preventDefault: jest.fn(), stopPropagation: jest.fn() }, payload); }; var returnsTrue = function returnsTrue() { return true; }; var returnsFalse = function returnsFalse() { return false; }; test('should call only handler', function () { var handler = jest.fn(returnsTrue); var callback = (0, _handle.handle)(handler); callback(makeEvent()); var expected = 1; expect(handler).toHaveBeenCalledTimes(expected); }); test('should call multiple handlers', function () { var handler1 = jest.fn(returnsTrue); var handler2 = jest.fn(returnsTrue); var callback = (0, _handle.handle)(handler1, handler2); callback(makeEvent()); var expected = 1; expect(handler1).toHaveBeenCalledTimes(expected); expect(handler2).toHaveBeenCalledTimes(expected); }); test('should skip non-function handlers', function () { var handler = jest.fn(returnsTrue); var callback = (0, _handle.handle)(null, void 0, 0, 'purple', handler); callback(makeEvent()); var expected = 1; expect(handler).toHaveBeenCalledTimes(expected); }); test('should not call handlers after one that returns false', function () { var handler1 = jest.fn(returnsTrue); var handler2 = jest.fn(returnsTrue); var callback = (0, _handle.handle)(handler1, returnsFalse, handler2); callback(makeEvent()); var expectedFirst = 1; expect(handler1).toHaveBeenCalledTimes(expectedFirst); expect(handler2).not.toHaveBeenCalled(); }); test('should call stopPropagation on event', function () { var callback = (0, _handle.handle)(_handle.stop); var ev = makeEvent(); callback(ev); var expected = 1; var actual = ev.stopPropagation; expect(actual).toHaveBeenCalledTimes(expected); }); test('should call preventDefault on event', function () { var callback = (0, _handle.handle)(_handle.preventDefault); var ev = makeEvent(); callback(ev); var expected = 1; var actual = ev.preventDefault; expect(actual).toHaveBeenCalledTimes(expected); }); test('should call any method on event', function () { var callback = (0, _handle.handle)((0, _handle.callOnEvent)('customMethod')); var ev = makeEvent({ customMethod: jest.fn() }); callback(ev); var expected = 1; var actual = ev.customMethod; expect(actual).toHaveBeenCalledTimes(expected); }); test('should only call handler for specified keyCode', function () { var keyCode = 13; var handler = jest.fn(); var callback = (0, _handle.handle)((0, _handle.forKeyCode)(keyCode), handler); callback(makeEvent()); expect(handler).not.toHaveBeenCalled(); callback(makeEvent({ keyCode: keyCode })); expect(handler).toHaveBeenCalled(); }); test('should only call handler for specified event prop', function () { var handler = jest.fn(); var prop = 'index'; var value = 0; var callback = (0, _handle.handle)((0, _handle.forEventProp)(prop, value), handler); // undefined shouldn't pass callback(makeEvent()); expect(handler).not.toHaveBeenCalled(); // == check shouldn't pass callback(makeEvent(_defineProperty({}, prop, false))); expect(handler).not.toHaveBeenCalled(); // === should pass callback(makeEvent(_defineProperty({}, prop, value))); expect(handler).toHaveBeenCalled(); }); test('should only call handler for specified prop', function () { var handler = jest.fn(); var callback = (0, _handle.handle)((0, _handle.forProp)('checked', true), handler); // undefined shouldn't pass callback({}, {}); expect(handler).not.toHaveBeenCalled(); // == check shouldn't pass callback({}, { checked: 1 }); expect(handler).not.toHaveBeenCalled(); // === should pass callback({}, { checked: true }); expect(handler).toHaveBeenCalled(); }); test('should forward events to function specified in provided props', function () { var event = 'onMyClick'; var prop = 'index'; var propValue = 0; var spy = jest.fn(); var props = _defineProperty({}, event, spy); var payload = _defineProperty({}, prop, propValue); (0, _handle.handle)((0, _handle.forward)(event))(payload, props); var expected = true; var actual = spy.mock.calls[0][0][prop] === propValue; expect(actual).toBe(expected); }); test('should forwardWithPrevent events to function specified in provided props when preventDefault() hasn\'t been called', function () { var event = 'onMyClick'; var handler = jest.fn(); var callback = (0, _handle.handle)((0, _handle.forwardWithPrevent)(event), handler); callback(); expect(handler).toHaveBeenCalledTimes(1); }); test('should not forwardWithPrevent events to function specified in provided props when preventDefault() has been called', function () { var event = 'onMyClick'; var handler = jest.fn(); var callback = (0, _handle.handle)((0, _handle.forwardWithPrevent)(event), handler); // should stop chain when `preventDefault()` has been called callback({}, { 'onMyClick': function onMyClick(ev) { return ev.preventDefault(); } }); expect(handler).not.toHaveBeenCalled(); }); test('should include object props as second arg when bound', function () { var componentInstance = { context: {}, props: { value: 1 } }; var handler = jest.fn(); var h = _handle.handle.bind(componentInstance); var callback = h(handler); callback(); var expected = 1; var actual = handler.mock.calls[0][1].value; expect(actual).toBe(expected); }); test('should include object context as third arg when bound', function () { var componentInstance = { context: { value: 1 }, props: {} }; var handler = jest.fn(); var h = _handle.handle.bind(componentInstance); var callback = h(handler); callback(); var expected = 1; var actual = handler.mock.calls[0][2].value; expect(actual).toBe(expected); }); describe('finally', function () { test('should call the finally callback when handle returns true', function () { var finallyCallback = jest.fn(); var callback = (0, _handle.handle)(returnsTrue)["finally"](finallyCallback); callback(makeEvent()); var expected = 1; expect(finallyCallback).toHaveBeenCalledTimes(expected); }); test('should call the finally callback when handle returns false', function () { var finallyCallback = jest.fn(); var callback = (0, _handle.handle)(returnsFalse)["finally"](finallyCallback); callback(makeEvent()); var expected = 1; expect(finallyCallback).toHaveBeenCalledTimes(expected); }); test('should call the finally callback when handle throws an error', function () { var finallyCallback = jest.fn(); var callback = (0, _handle.handle)(function () { throw new Error('Something has gone awry ...'); })["finally"](finallyCallback); try { callback(makeEvent()); } catch (e) { // we don't want the error to interrupt the test } var expected = 1; expect(finallyCallback).toHaveBeenCalledTimes(expected); }); }); describe('#oneOf', function () { test('should call each handler until one passes', function () { var handler = jest.fn(returnsTrue); var h1 = [returnsFalse, handler]; var h2 = [returnsTrue, handler]; var callback = (0, _handle.oneOf)(h1, h1, h2); callback(); var expected = 1; expect(handler).toHaveBeenCalledTimes(expected); }); test('should stop if the first handler passes', function () { var handler = jest.fn(returnsTrue); var callback = (0, _handle.oneOf)([returnsTrue, handler], [returnsTrue, handler], [returnsTrue, handler]); callback(); var expected = 1; expect(handler).toHaveBeenCalledTimes(expected); }); test('should pass args to condition', function () { var handler = jest.fn(returnsTrue); var callback = (0, _handle.oneOf)([handler, returnsTrue]); var ev = { value: 1 }; callback(ev); var expected = ev; var actual = handler.mock.calls[0][0]; expect(actual).toBe(expected); }); test('should pass args to handlers', function () { var handler = jest.fn(returnsTrue); var callback = (0, _handle.oneOf)([returnsTrue, handler]); var ev = { value: 1 }; callback(ev); var expected = ev; var actual = handler.mock.calls[0][0]; expect(actual).toBe(expected); }); test('should return true when the passed condition branch returns a truthy value', function () { var callback = (0, _handle.oneOf)([returnsTrue, function () { return 'ok'; }]); var expected = true; var actual = callback(); expect(actual).toBe(expected); }); test('should return false when the passed condition branch returns a falsy value', function () { var callback = (0, _handle.oneOf)([returnsTrue, function () { return null; }]); var expected = false; var actual = callback(); expect(actual).toBe(expected); }); test('should return false when no conditions pass', function () { var callback = (0, _handle.oneOf)([returnsFalse, returnsTrue], [returnsFalse, returnsTrue]); var expected = false; var actual = callback(); expect(actual).toBe(expected); }); test('should support bound handlers', function () { var componentInstance = { props: {}, context: { value: 1 } }; var handler = jest.fn(); var h = _handle.handle.bind(componentInstance); var callback = (0, _handle.oneOf)([returnsTrue, h(handler)]); callback(); var expected = 1; var actual = handler.mock.calls[0][2].value; expect(actual).toBe(expected); }); test('should include object props as second arg when bound', function () { var componentInstance = { props: { value: 1 }, context: {} }; var handler = jest.fn(); var o = _handle.oneOf.bind(componentInstance); var callback = o([returnsTrue, handler]); callback(); var expected = 1; var actual = handler.mock.calls[0][1].value; expect(actual).toBe(expected); }); test('should include object context as third arg when bound', function () { var componentInstance = { props: {}, context: { value: 1 } }; var handler = jest.fn(); var o = _handle.oneOf.bind(componentInstance); var callback = o([returnsTrue, handler]); callback(); var expected = 1; var actual = handler.mock.calls[0][2].value; expect(actual).toBe(expected); }); test('should support finally callback', function () { var handler = jest.fn(); var callback = (0, _handle.oneOf)([returnsFalse, returnsTrue], [returnsFalse, returnsTrue])["finally"](handler); callback(); var expected = 1; expect(handler).toHaveBeenCalledTimes(expected); }); }); describe('#adaptEvent', function () { test('should pass the adapted event payload to the provided handler', function () { var handler = jest.fn(); var onlyValue = function onlyValue(_ref) { var value = _ref.value; return { value: value }; }; var ev = { value: 1, message: 'ok' }; (0, _handle.adaptEvent)(onlyValue, handler)(ev); var expected = { value: 1 }; var actual = handler.mock.calls[0][0]; expect(actual).toEqual(expected); }); test('should pass additional arguments to the provided handler', function () { var handler = jest.fn(); var returnOne = function returnOne() { return 1; }; (0, _handle.adaptEvent)(returnOne, handler)(0, 2, 3); var expected = [1, 2, 3]; var actual = handler.mock.calls[0]; expect(actual).toEqual(expected); }); test('should support bound adapter function', function () { var obj = { adapt: function adapt() { return 1; } }; var handler = jest.fn(); var fn = (0, _handle.adaptEvent)((0, _handle.call)('adapt'), handler).bind(obj); fn(0, 2, 3); var expected = [1, 2, 3]; var actual = handler.mock.calls[0]; expect(actual).toEqual(expected); }); test('should support bound handler function', function () { var obj = { handler: jest.fn() }; var returnOne = function returnOne() { return 1; }; var fn = (0, _handle.adaptEvent)(returnOne, (0, _handle.call)('handler')).bind(obj); fn(0, 2, 3); var expected = [1, 2, 3]; var actual = obj.handler.mock.calls[0]; expect(actual).toEqual(expected); }); }); describe('#forwardCustom', function () { test('should pass an object with `type` when no adapter is provided', function () { var handler = jest.fn(); (0, _handle.forwardCustom)('onCustomEvent')(null, { onCustomEvent: handler }); var expected = { type: 'onCustomEvent' }; var actual = handler.mock.calls[0][0]; expect(actual).toEqual(expected); }); test('should add `type` to object returned by adapter', function () { var handler = jest.fn(); var adapter = function adapter() { return { index: 0 }; }; (0, _handle.forwardCustom)('onCustomEvent', adapter)(null, { onCustomEvent: handler }); var expected = { type: 'onCustomEvent', index: 0 }; var actual = handler.mock.calls[0][0]; expect(actual).toEqual(expected); }); test('should create an event payload if the adapter returns nothing', function () { var handler = jest.fn(); var adapter = function adapter() { return null; }; (0, _handle.forwardCustom)('onCustomEvent', adapter)(null, { onCustomEvent: handler }); var expected = { type: 'onCustomEvent' }; var actual = handler.mock.calls[0][0]; expect(actual).toEqual(expected); }); test('should pass event, props, and context args to adapter', function () { var adapter = jest.fn(); var args = [1, // ev, 2, // props, 3 // context ]; (0, _handle.forwardCustom)('onCustomEvent', adapter).apply(void 0, args); var expected = args; var actual = adapter.mock.calls[0]; expect(actual).toEqual(expected); }); test('should support bound adapter function', function () { var handler = jest.fn(); var expected = 'ok'; var obj = { data: expected, adapter: function adapter() { return { value: this === null || this === void 0 ? void 0 : this.data }; } }; var forwarderFn = (0, _handle.forwardCustom)('onCustomEvent', obj.adapter).bind(obj); forwarderFn(null, { onCustomEvent: handler }, null); var actual = handler.mock.calls[0][0]; expect(actual).toEqual(expect.objectContaining({ value: expected })); }); test('should support bound adapter function by call', function () { var handler = jest.fn(); var expected = 'ok'; var obj = { data: expected, adapter: function adapter() { return { value: this === null || this === void 0 ? void 0 : this.data }; } }; var forwarderFn = (0, _handle.forwardCustom)('onCustomEvent', (0, _handle.call)('adapter')).bind(obj); forwarderFn(null, { onCustomEvent: handler }, null); var actual = handler.mock.calls[0][0]; expect(actual).toEqual(expect.objectContaining({ value: expected })); }); test('should support bound adapter function by handle', function () { var handler = jest.fn(); var expected = 'ok'; var TestComponent = /*#__PURE__*/function (_Component) { function TestComponent(props) { var _this; _classCallCheck(this, TestComponent); _this = _callSuper(this, TestComponent, [props]); _this.data = expected; (0, _handle.handle)((0, _handle.forwardCustom)('onCustomEvent', (0, _handle.call)('adapter'))).bindAs(_this, 'handleCustomEvent'); return _this; } _inherits(TestComponent, _Component); return _createClass(TestComponent, [{ key: "componentDidMount", value: function componentDidMount() { this.handleCustomEvent(null, this.props, this.context); } }, { key: "adapter", value: function adapter() { return { value: this === null || this === void 0 ? void 0 : this.data }; } }, { key: "render", value: function render() { return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {}); } }]); }(_react.Component); TestComponent.propTypes = { onCustomEvent: _propTypes["default"].func }; (0, _react2.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(TestComponent, { onCustomEvent: handler })); var actual = handler.mock.calls[0][0]; expect(actual).toEqual(expect.objectContaining({ value: expected })); }); }); describe('#forwardCustomWithPrevent', function () { test('should pass an object with `type` and `preventDefault` when no adapter is provided', function () { var handler = jest.fn(); (0, _handle.forwardCustomWithPrevent)('onCustomEvent')(null, { onCustomEvent: handler }); var actual = handler.mock.calls[0][0]; expect(actual).toEqual(expect.objectContaining({ type: 'onCustomEvent', preventDefault: expect.any(Function) })); }); test('should add `type` and `preventDefault` to object returned by adapter', function () { var handler = jest.fn(); var adapter = function adapter() { return { index: 0 }; }; (0, _handle.forwardCustomWithPrevent)('onCustomEvent', adapter)(null, { onCustomEvent: handler }); var actual = handler.mock.calls[0][0]; expect(actual).toEqual(expect.objectContaining({ type: 'onCustomEvent', preventDefault: expect.any(Function), index: 0 })); }); test('should create an event payload if the adapter returns nothing', function () { var handler = jest.fn(); var adapter = function adapter() { return null; }; (0, _handle.forwardCustomWithPrevent)('onCustomEvent', adapter)(null, { onCustomEvent: handler }); var actual = handler.mock.calls[0][0]; expect(actual).toEqual(expect.objectContaining({ type: 'onCustomEvent', preventDefault: expect.any(Function) })); }); test('should pass an object with `preventDefault` and `stopPropagation` when event has them', function () { var ev = { preventDefault: jest.fn(), stopPropagation: function stopPropagation() {} }; var handler = jest.fn(); var adapter = function adapter() { return null; }; (0, _handle.forwardCustomWithPrevent)('onCustomEvent', adapter)(ev, { onCustomEvent: handler }); var actual = handler.mock.calls[0][0]; expect(actual).toEqual(expect.objectContaining({ type: 'onCustomEvent', preventDefault: expect.any(Function), stopPropagation: expect.any(Function) })); actual.preventDefault(); expect(ev.preventDefault).toHaveBeenCalled(); }); test('should pass event, props, and context args to adapter', function () { var adapter = jest.fn(); var args = [1, // ev, 2, // props, 3 // context ]; (0, _handle.forwardCustomWithPrevent)('onCustomEvent', adapter).apply(void 0, args); var expected = args; var actual = adapter.mock.calls[0]; expect(actual).toEqual(expected); }); test('should support bound adapter function', function () { var handler = jest.fn(); var expected = 'ok'; var obj = { data: expected, adapter: function adapter() { return { value: this === null || this === void 0 ? void 0 : this.data }; } }; var forwarderFn = (0, _handle.forwardCustomWithPrevent)('onCustomEvent', obj.adapter).bind(obj); forwarderFn(null, { onCustomEvent: handler }, null); var actual = handler.mock.calls[0][0]; expect(actual).toEqual(expect.objectContaining({ value: expected })); }); test('should support bound adapter function by call', function () { var handler = jest.fn(); var expected = 'ok'; var obj = { data: expected, adapter: function adapter() { return { value: this === null || this === void 0 ? void 0 : this.data }; } }; var forwarderFn = (0, _handle.forwardCustomWithPrevent)('onCustomEvent', (0, _handle.call)('adapter')).bind(obj); forwarderFn(null, { onCustomEvent: handler }, null); var actual = handler.mock.calls[0][0]; expect(actual).toEqual(expect.objectContaining({ value: expected })); }); test('should support bound adapter function by handle', function () { var handler = jest.fn(); var expected = 'ok'; var TestComponent = /*#__PURE__*/function (_Component2) { function TestComponent(props) { var _this2; _classCallCheck(this, TestComponent); _this2 = _callSuper(this, TestComponent, [props]); _this2.data = expected; (0, _handle.handle)((0, _handle.forwardCustomWithPrevent)('onCustomEvent', (0, _handle.call)('adapter'))).bindAs(_this2, 'handleCustomEvent'); return _this2; } _inherits(TestComponent, _Component2); return _createClass(TestComponent, [{ key: "componentDidMount", value: function componentDidMount() { this.handleCustomEvent(null, this.props, this.context); } }, { key: "adapter", value: function adapter() { return { value: this === null || this === void 0 ? void 0 : this.data }; } }, { key: "render", value: function render() { return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {}); } }]); }(_react.Component); TestComponent.propTypes = { onCustomEvent: _propTypes["default"].func }; (0, _react2.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(TestComponent, { onCustomEvent: handler })); var actual = handler.mock.calls[0][0]; expect(actual).toEqual(expect.objectContaining({ value: expected })); }); test('should call the next handler when `preventDefault` from provided props hasn\'t been called', function () { var event = 'onMyClick'; var handler = jest.fn(); var callback = (0, _handle.handle)((0, _handle.forwardCustomWithPrevent)(event), handler); callback(); expect(handler).toHaveBeenCalledTimes(1); }); test('should not call the next handler when `preventDefault` from provided props has been called', function () { var event = 'onMyClick'; var handler = jest.fn(); var callback = (0, _handle.handle)((0, _handle.forwardCustomWithPrevent)(event), handler); // should stop chain when `preventDefault()` has been called callback({}, { 'onMyClick': function onMyClick(ev) { return ev.preventDefault(); } }); expect(handler).not.toHaveBeenCalled(); }); }); });