UNPKG

wix-style-react

Version:
392 lines (311 loc) • 15.1 kB
'use strict'; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _enzyme = require('enzyme'); var _Button = require('../../Button'); var _Button2 = _interopRequireDefault(_Button); var _driverFactory = require('wix-ui-test-utils/driver-factory'); var _FocusableHOC = require('./FocusableHOC'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var focusableDriver = function focusableDriver(_ref) { var element = _ref.element, eventTrigger = _ref.eventTrigger; return { focus: function focus() { return eventTrigger.focus(element); }, blur: function blur() { return eventTrigger.blur(element); }, hasFocusState: function hasFocusState() { return !!element.getAttribute('data-focus'); }, hasFocusVisibleState: function hasFocusVisibleState() { return !!element.getAttribute('data-focus-visible'); } }; }; describe('FocusableHOC', function () { var _class, _temp; var render = function render(Comp) { return (0, _enzyme.mount)(Comp, { attachTo: document.createElement('div') }); }; // Pure component without state var PureChildComponent = (_temp = _class = function (_React$PureComponent) { _inherits(PureChildComponent, _React$PureComponent); function PureChildComponent(props) { _classCallCheck(this, PureChildComponent); var _this = _possibleConstructorReturn(this, (PureChildComponent.__proto__ || Object.getPrototypeOf(PureChildComponent)).call(this, props)); _this.id = props.id; _this.boundMethod = _this.boundMethod.bind(_this); return _this; } _createClass(PureChildComponent, [{ key: 'unboundMethod', value: function unboundMethod() { return 'unboundMethod'; } }, { key: 'boundMethod', value: function boundMethod() { return this.id; } }, { key: 'render', value: function render() { return _react2.default.createElement( 'div', _extends({ onFocus: this.props.focusableOnFocus // eslint-disable-line react/prop-types , onBlur: this.props.focusableOnBlur // eslint-disable-line react/prop-types }, (0, _FocusableHOC.focusableStates)(this.props)), 'Hello' ); } }], [{ key: 'staticMethod', value: function staticMethod() { return 'staticMethod'; } }]); return PureChildComponent; }(_react2.default.PureComponent), _class.propTypes = { id: _propTypes2.default.string }, _class.staticVariable = 'staticVariable', _temp); var pureChildDriverFactory = function pureChildDriverFactory(_ref2) { var element = _ref2.element, eventTrigger = _ref2.eventTrigger; return _extends({}, focusableDriver({ element: element, getFocusableElement: function getFocusableElement() { return element; }, eventTrigger: eventTrigger })); }; var WithFocusableComp = (0, _FocusableHOC.withFocusable)(PureChildComponent); describe('Pure component HOC', function () { it('should render the wrapped component', function () { var wrapper = render(_react2.default.createElement(WithFocusableComp, null)); expect(wrapper.children().instance()).toBeInstanceOf(PureChildComponent); }); describe('hoisting', function () { it('should hoist static methods', function () { expect(WithFocusableComp.staticMethod()).toEqual('staticMethod'); }); it('should hoist static variables', function () { expect(WithFocusableComp.staticVariable).toEqual('staticVariable'); }); it('should hoist prototype methods from child to HOC and bind them', function () { var wrapper = render(_react2.default.createElement(WithFocusableComp, { id: 'some_id' })); expect(wrapper.instance().unboundMethod()).toEqual('unboundMethod'); expect(wrapper.instance().boundMethod()).toEqual('some_id'); }); }); }); describe('Focusable', function () { var driverFactory = (0, _driverFactory.createDriverFactory)(pureChildDriverFactory); var createDriver = function createDriver(Component) { var driver = driverFactory(Component); var fireMouseDown = function fireMouseDown() { return window.dispatchEvent(new window.Event('mousedown')); }; var fireMouseUp = function fireMouseUp() { return window.dispatchEvent(new window.Event('mouseup')); }; var fireKeyDown = function fireKeyDown() { return window.dispatchEvent(new window.Event('keydown')); }; var fireKeyUp = function fireKeyUp() { return window.dispatchEvent(new window.Event('keyup')); }; var tabOut = function tabOut() { fireKeyDown(); driver.blur(); fireKeyUp(); }; var tabIn = function tabIn() { fireKeyDown(); driver.focus(); fireKeyUp(); }; var click = function click() { fireMouseDown(); driver.focus(); fireMouseUp(); }; return _extends({}, driver, { fireMouseDown: fireMouseDown, fireKeyDown: fireKeyDown, fireKeyUp: fireKeyUp, tabOut: tabOut, tabIn: tabIn, click: click }); }; var expectKeyboardFocused = function expectKeyboardFocused(driver, msg) { var prefix = msg ? msg + ' - ' : ''; expect(driver.hasFocusState()).toBe(true, prefix + 'hasFocusState'); expect(driver.hasFocusVisibleState()).toBe(true, prefix + 'hasFocusVisibleState'); }; var expectNotFocused = function expectNotFocused(driver, msg) { var prefix = msg ? msg + ' - ' : ''; expect(driver.hasFocusState()).toBe(false, prefix + 'hasFocusState'); expect(driver.hasFocusVisibleState()).toBe(false, prefix + 'hasFocusVisibleState'); }; var expectMouseFocused = function expectMouseFocused(driver, msg) { var prefix = msg ? msg + ' - ' : ''; expect(driver.hasFocusState()).toBe(true, prefix + 'hasFocusState'); expect(driver.hasFocusVisibleState()).toBe(false, prefix + 'hasFocusVisibleState'); }; var WithFocusableComp2 = void 0; var focusableModule = void 0; beforeEach(function () { // Reseting modules, in order to reset the FocusableHOC.InputMethod.method state. jest.resetModules(); focusableModule = require('./FocusableHOC'); WithFocusableComp2 = focusableModule.withFocusable(PureChildComponent); // TODO: find a way to reset the eventHandlers which are added to the window. }); it('should not have focus nor focus-visible [given] initial render', function () { var driver = createDriver(_react2.default.createElement(WithFocusableComp2, null)); expectNotFocused(driver); }); it('should have focus and focus-visible [when] focused programatically', function () { var driver = createDriver(_react2.default.createElement(WithFocusableComp2, null)); driver.focus(); // Default input is keyboard expectKeyboardFocused(driver, 'after focus'); }); it('should have focus and focus-visible [when] tabbed in', function () { var driver = createDriver(_react2.default.createElement(WithFocusableComp2, null)); driver.tabIn(); expectKeyboardFocused(driver, 'after focus'); }); it('should have focus and focus-visible [when] tabbed in withot keyDown', function () { // This test case checks a scenario when the focus is on the browser's // url input, and we press tab. The keyDown is not fired. var driver = createDriver(_react2.default.createElement(WithFocusableComp2, null)); driver.focus(); driver.fireKeyUp(); expectKeyboardFocused(driver, 'after focus'); }); it('should not have focus nor focus-visible [when] blured programatically [given] keyboard focused', function () { var driver = createDriver(_react2.default.createElement(WithFocusableComp2, null)); driver.tabIn(); expectKeyboardFocused(driver, 'after focus'); driver.blur(); expectNotFocused(driver, 'after blur'); }); it('should have focus but not focus-visible [when] clicked', function () { var driver = createDriver(_react2.default.createElement(WithFocusableComp2, null)); driver.click(); expectMouseFocused(driver, 'after click'); }); it('should have focus but not focus-visible [when] focused programatically [given] current input method is mouse', function () { // This test must be here , after a test which finishes with the input method = mouse. // this test is only to test that we are reseting the FocusableHOC global state proparely, // usin the jest.resetModules() call. var driver = createDriver(_react2.default.createElement(WithFocusableComp2, null)); driver.focus(); expectKeyboardFocused(driver, 'after click'); }); /** * This test checks that the InpurMethod.method state is updated to `keyboard` after * is was set to `mouse`. */ it('should have focus and focus-visible [when] focused [given] mouseDown and blur', function () { var driver = createDriver(_react2.default.createElement(WithFocusableComp2, null)); driver.click(); expectMouseFocused(driver, 'after click'); driver.blur(); expectNotFocused(driver, 'after blur'); driver.tabIn(); expectKeyboardFocused(driver, 'after focus'); }); it('should not be focused [when] tabbed out [given] focused by mouse', function () { var driver = createDriver(_react2.default.createElement(WithFocusableComp, null)); driver.click(); expectMouseFocused(driver, 'after click'); driver.tabOut(); expectNotFocused(driver, 'after tab'); }); it('should have focus and focus-visible, when: any keyboard key pressed [given] focused by mouse', function () { var driver = createDriver(_react2.default.createElement(WithFocusableComp, null)); driver.click(); expectMouseFocused(driver, 'after click'); driver.fireKeyDown(); expectKeyboardFocused(driver, 'after pressing space'); }); }); describe('regressions', function () { var ButtonWithDisabledState = function (_React$Component) { _inherits(ButtonWithDisabledState, _React$Component); function ButtonWithDisabledState() { var _ref3; var _temp2, _this2, _ret; _classCallCheck(this, ButtonWithDisabledState); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _ret = (_temp2 = (_this2 = _possibleConstructorReturn(this, (_ref3 = ButtonWithDisabledState.__proto__ || Object.getPrototypeOf(ButtonWithDisabledState)).call.apply(_ref3, [this].concat(args))), _this2), _this2.state = { disabled: false }, _this2.handleButtonClick = function () { _this2.setState({ disabled: true }); }, _temp2), _possibleConstructorReturn(_this2, _ret); } _createClass(ButtonWithDisabledState, [{ key: 'render', value: function render() { var _this3 = this; return _react2.default.createElement( 'div', null, _react2.default.createElement( _Button2.default, { dataHook: 'disabled-button', disabled: this.state.disabled, onClick: this.handleButtonClick }, 'click me' ), _react2.default.createElement('input', { placeholder: 'click the button and type here', onChange: function onChange() { return _this3.setState({ disabled: false }); } }) ); } }]); return ButtonWithDisabledState; }(_react2.default.Component); it('ISSUE-1721: Fix focusable button in disabled state', function () { var component = (0, _enzyme.mount)(_react2.default.createElement(ButtonWithDisabledState, null)); var button = component.find('button'); var input = component.find('input'); /* by default should not have focus and should not be disabled */ expect(button.getDOMNode().disabled).toBeFalsy(); expect(button.getDOMNode().attributes['data-focus']).toBeFalsy(); /* become focused */ button.simulate('focus'); expect(button.getDOMNode().attributes['data-focus']).toBeTruthy(); /* click on button after that, button should become disabled */ button.simulate('click'); expect(button.getDOMNode().disabled).toBeTruthy(); /* bug was here, after button become disabled, focus should disappear */ expect(button.getDOMNode().attributes['data-focus']).toBeFalsy(); /* input change, after that should be disabled === false */ input.simulate('change', { target: { value: '123' } }); expect(button.getDOMNode().disabled).toBeFalsy(); /* bug was here, after input change, button should become unfocused */ expect(button.getDOMNode().attributes['data-focus']).toBeFalsy(); }); }); });