UNPKG

@enact/sandstone

Version:

Large-screen/TV support library for Enact, containing a variety of UI components.

529 lines (527 loc) 22.1 kB
"use strict"; var _FloatingLayer = require("@enact/ui/FloatingLayer"); require("@testing-library/jest-dom"); var _react = require("@testing-library/react"); var _userEvent = _interopRequireDefault(require("@testing-library/user-event")); var _Input = _interopRequireDefault(require("../Input")); var _jsxRuntime = require("react/jsx-runtime"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } var FloatingLayerController = (0, _FloatingLayer.FloatingLayerDecorator)('div'); describe('Input specs', function () { test('should be rendered opened if open is set to true', function () { (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { open: true }) })); var actual = _react.screen.getAllByLabelText('- Input field')[0].parentElement.nextElementSibling.children.length > 0; expect(actual).toBeTruthy(); }); test('should set title when there is title text', function () { var str = 'title text'; (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { open: true, title: str }) })); var titleField = _react.screen.getByText(str).parentElement.parentElement; var expected = 'title'; expect(titleField).toBeInTheDocument(); expect(titleField).toHaveClass(expected); }); test('should set title below when there is title below text', function () { var str = 'title below text'; (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { open: true, subtitle: str }) })); var subtitleField = _react.screen.getByText(str).parentElement.parentElement; var expected = 'subtitle'; expect(subtitleField).toBeInTheDocument(); expect(subtitleField).toHaveClass(expected); }); test('should set value at input when there is value text', function () { var str = 'value text'; (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { open: true, value: str }) })); var inputField = _react.screen.getByPlaceholderText('-'); expect(inputField).toHaveValue(str); }); test('should set placeholder at input when there is placeholder text', function () { var str = 'placeholder text'; (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { open: true, placeholder: str }) })); var inputField = _react.screen.getByPlaceholderText(str); var expectedAttribute = 'placeholder'; expect(inputField).toHaveAttribute(expectedAttribute, str); }); test('should set type to password at input when input type is `password`', function () { var str = 'placeholder text'; (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { open: true, placeholder: str, type: "password" }) })); var inputField = _react.screen.getByPlaceholderText(str); var expectedAttribute = 'type'; var expectedValue = 'password'; expect(inputField).toHaveAttribute(expectedAttribute, expectedValue); }); test('should set `spellcheck=false` attribute when type is `password`', function () { var str = 'placeholder text'; (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { placeholder: str, open: true, type: "password" }) })); var inputField = _react.screen.getByPlaceholderText(str); var expectedAttribute = 'spellcheck'; var expectedValue = 'false'; expect(inputField).toHaveAttribute(expectedAttribute, expectedValue); }); test('should set type to url at input when input type is `url`', function () { var str = 'placeholder text'; (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { open: true, placeholder: str, type: "url" }) })); var inputField = _react.screen.getByPlaceholderText(str); var expectedAttribute = 'type'; var expectedValue = 'url'; expect(inputField).toHaveAttribute(expectedAttribute, expectedValue); }); test('should set disabled at button when popup is disabled', function () { (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { disabled: true })); var buttonInput = _react.screen.getByRole('button'); var expectedAttribute = 'aria-disabled'; var expectedValue = 'true'; expect(buttonInput).toHaveAttribute(expectedAttribute, expectedValue); }); test('should fire `onOpenPopup` and `onShow` with type when open', /*#__PURE__*/_asyncToGenerator(function* () { var handleOpenPopup = jest.fn(); var handleShow = jest.fn(); var user = _userEvent["default"].setup(); (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { onOpenPopup: handleOpenPopup, onShow: handleShow }) })); yield user.click(_react.screen.getByRole('button')); var openExpected = { type: 'onOpenPopup' }; var openActual = handleOpenPopup.mock.calls.length && handleOpenPopup.mock.calls[0][0]; var showExpected = { type: 'onShow' }; var showActual = handleShow.mock.calls.length && handleShow.mock.calls[0][0]; expect(openActual).toMatchObject(openExpected); expect(showActual).toMatchObject(showExpected); })); test('should fire `onBeforeChange` and `onChange` with type when value changed', /*#__PURE__*/_asyncToGenerator(function* () { var handleBeforeChange = jest.fn(); var handleChange = jest.fn(); var user = _userEvent["default"].setup(); (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { onBeforeChange: handleBeforeChange, onChange: handleChange, open: true }) })); yield user.type(_react.screen.getByPlaceholderText('-'), 'a'); var beforeExpected = { type: 'onBeforeChange' }; var beforeActual = handleBeforeChange.mock.calls.length && handleBeforeChange.mock.calls[0][0]; var changeExpected = { type: 'onChange' }; var changeActual = handleChange.mock.calls.length && handleChange.mock.calls[0][0]; expect(beforeActual).toMatchObject(beforeExpected); expect(changeActual).toMatchObject(changeExpected); })); test('should fire `onClose` and `onComplete` with type when enter key pressed', function () { var handleClose = jest.fn(); var handleComplete = jest.fn(); (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { onClose: handleClose, onComplete: handleComplete, open: true }) })); _react.fireEvent.keyDown(_react.screen.getByPlaceholderText('-'), { keyCode: 13 }); var closeExpected = { type: 'onClose' }; var closeActual = handleClose.mock.calls.length && handleClose.mock.calls[0][0]; var completeExpected = { type: 'onComplete' }; var completeActual = handleComplete.mock.calls.length && handleComplete.mock.calls[0][0]; expect(closeActual).toMatchObject(closeExpected); expect(completeActual).toMatchObject(completeExpected); }); // Type = number describe('of type number', function () { test('should be rendered opened if open is set to true', function () { (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { type: "number", open: true, length: 4 }) })); var actual = _react.screen.getAllByLabelText('- Input field')[0].parentElement.nextElementSibling.children.length > 0; expect(actual).toBeTruthy(); }); test('should set title when there is title text', function () { var str = 'title text'; (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { type: "number", open: true, length: 4, title: str }) })); var titleField = _react.screen.getByText(str).parentElement.parentElement; var expected = 'title'; expect(titleField).toBeInTheDocument(); expect(titleField).toHaveClass(expected); }); test('should set title below when there is title below text', function () { var str = 'title below text'; (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { type: "number", open: true, length: 4, subtitle: str }) })); var subtitleField = _react.screen.getByText(str).parentElement.parentElement; var expected = 'subtitle'; expect(subtitleField).toBeInTheDocument(); expect(subtitleField).toHaveClass(expected); }); test('should set value at input when there is value text', function () { var str = '1234'; (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { type: "number", open: true, length: 4, value: str }) })); var expected = str; var actual = _react.screen.getByRole('list').textContent; expect(actual).toBe(expected); }); test('should set disabled at button when the component is disabled', function () { (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { type: "number", length: 4, disabled: true })); var buttonInput = _react.screen.getByRole('button'); var expectedAttribute = 'aria-disabled'; var expectedValue = 'true'; expect(buttonInput).toHaveAttribute(expectedAttribute, expectedValue); }); test('should not be able to add more characters when the maxlength is reached', /*#__PURE__*/_asyncToGenerator(function* () { var spy = jest.fn(); var user = _userEvent["default"].setup(); (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { type: "number", minLength: 1, maxLength: 4, open: true, onChange: spy, value: "1234" }) })); var numberButton = _react.screen.getByText('6'); yield user.click(numberButton); expect(spy).not.toHaveBeenCalled(); })); test('should include a submit button when `minLength` !== `maxLength` for number input', function () { (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { "data-testid": "input", children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { type: "number", minLength: 4, maxLength: 6, open: true }) })); var buttonSubmit = _react.screen.getByText('Submit'); expect(buttonSubmit).not.toBeNull(); }); test('should include a submit button for implicit joined number input', function () { (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { type: "number", length: 10, open: true }) })); var buttonSubmit = _react.screen.getByText('Submit'); expect(buttonSubmit).not.toBeNull(); }); test('should include a submit button for explicit joined number input', function () { (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { type: "number", length: 4, open: true, numberInputField: "joined" }) })); var buttonSubmit = _react.screen.getByText('Submit'); expect(buttonSubmit).not.toBeNull(); }); test('should exclude a submit button when separated number input', function () { (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { type: "number", length: 4, open: true }) })); var buttonSubmit = _react.screen.queryByText('Submit'); expect(buttonSubmit).toBeNull(); }); test('should exclude a submit button for explicit separated number input', function () { (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { type: "number", length: 10, open: true, numberInputField: "separated" }) })); var buttonSubmit = _react.screen.queryByText('Submit'); expect(buttonSubmit).toBeNull(); }); test('should show an invalid tooltip if invalid and message supplied', function () { (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { type: "number", open: true, length: 10, invalid: true, invalidMessage: "Invalid" }) })); var invalidTextField = _react.screen.getByText('Invalid').parentElement.parentElement; var expected = 'tooltipLabel'; expect(invalidTextField).toHaveClass(expected); }); test('should not show invalid tooltip if not invalid but message supplied', function () { (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { type: "number", open: true, length: 10, invalidMessage: "Invalid" }) })); var actual = _react.screen.queryByText('Invalid'); expect(actual).toBeNull(); }); test('should show an invalid tooltip if invalid and no message supplied', function () { (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { type: "number", open: true, length: 10, invalid: true }) })); var invalidTextField = _react.screen.getByText('Please enter a valid value.').parentElement.parentElement; var expected = 'tooltipLabel'; expect(invalidTextField).toHaveClass(expected); }); test('should not show an invalid tooltip if invalid and message is falsy', function () { (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { type: "number", open: true, length: 10, invalid: true, invalidMessage: "" }) })); var expected = 1; var actual = _react.screen.getAllByRole('button')[2].parentElement.previousElementSibling.previousElementSibling.children.length; expect(actual).toBe(expected); }); test('should call onComplete when submit button clicked', /*#__PURE__*/_asyncToGenerator(function* () { jest.useFakeTimers(); var spy = jest.fn(); var user = _userEvent["default"].setup({ advanceTimers: jest.advanceTimersByTime }); (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { type: "number", minLength: 1, maxLength: 4, open: true, onComplete: spy }) })); var numberButton = _react.screen.getByText('2'); var submitButton = _react.screen.getByText('Submit'); yield user.click(numberButton); yield user.click(submitButton); (0, _react.act)(function () { return jest.advanceTimersByTime(300); }); expect(spy).toHaveBeenCalled(); jest.useRealTimers(); })); test('should call onChange when submit button clicked', /*#__PURE__*/_asyncToGenerator(function* () { var spy = jest.fn(); var user = _userEvent["default"].setup(); (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { type: "number", minLength: 1, maxLength: 4, open: true, onChange: spy }) })); var numberButton = _react.screen.getByText('2'); var submitButton = _react.screen.getByText('Submit'); yield user.click(numberButton); yield user.click(submitButton); expect(spy).toHaveBeenCalled(); })); test('should call onBeforeChange once when input occurs', /*#__PURE__*/_asyncToGenerator(function* () { var spy = jest.fn(); var user = _userEvent["default"].setup(); (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { type: "number", open: true, length: 10, onBeforeChange: spy }) })); var numberButton = _react.screen.getByText('2'); yield user.click(numberButton); expect(spy).toHaveBeenCalled(); })); test('should prevent input when onBeforeChange calls preventDefault', /*#__PURE__*/_asyncToGenerator(function* () { var spy = jest.fn(); var mock = jest.fn(function (ev) { if (ev.value === '2') { ev.preventDefault(); } }); var user = _userEvent["default"].setup(); (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { type: "number", minLength: 1, maxLength: 4, open: true, onBeforeChange: mock, onChange: spy }) })); var numberButton2 = _react.screen.getByText('2'); var numberButton1 = _react.screen.getByText('1'); var submitButton = _react.screen.getByText('Submit'); yield user.click(numberButton2); yield user.click(numberButton1); yield user.click(submitButton); var expected = 1; expect(spy).toHaveBeenCalledTimes(expected); })); test('should delete an input when delete button clicked', /*#__PURE__*/_asyncToGenerator(function* () { var spy = jest.fn(); var user = _userEvent["default"].setup(); (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { type: "number", value: "12", minLength: 1, maxLength: 4, open: true, onChange: spy }) })); var backspaceButton = _react.screen.getByText('␈'); yield user.click(backspaceButton); var expected = '1'; var actual = _react.screen.getByRole('list').textContent; expect(spy).toHaveBeenCalled(); expect(actual).toBe(expected); })); test('should call onBeforeChange when delete button clicked', /*#__PURE__*/_asyncToGenerator(function* () { var spy = jest.fn(); var user = _userEvent["default"].setup(); (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { type: "number", value: "12", minLength: 1, maxLength: 4, open: true, onBeforeChange: spy }) })); var backspaceButton = _react.screen.getByText('␈'); yield user.click(backspaceButton); var expected = '1'; var actual = _react.screen.getByRole('list').textContent; expect(spy).toHaveBeenCalled(); expect(actual).toBe(expected); })); test('should not include a submit button when noSubmitButton is used', function () { (0, _react.render)( /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingLayerController, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], { type: "number", length: 4, open: true, numberInputField: "joined", noSubmitButton: true }) })); var buttonSubmit = _react.screen.queryByText('Submit'); expect(buttonSubmit).toBeNull(); }); }); });