react-time-picker
Advanced tools
Comparing version 4.5.0 to 5.0.0
@@ -52,3 +52,3 @@ "use strict"; | ||
function _extends() { _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; }; return _extends.apply(this, arguments); } | ||
function _extends() { _extends = Object.assign ? Object.assign.bind() : 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; }; return _extends.apply(this, arguments); } | ||
@@ -63,3 +63,3 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | ||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | ||
@@ -74,3 +74,3 @@ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } | ||
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | ||
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | ||
@@ -91,2 +91,3 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
var getFormatterOptionsCache = {}; | ||
var allViews = ['hour', 'minute', 'second']; | ||
@@ -99,4 +100,4 @@ | ||
function isValidInput(element) { | ||
return element.tagName === 'INPUT' && element.type === 'number'; | ||
function isInternalInput(element) { | ||
return element.dataset.input === 'true'; | ||
} | ||
@@ -109,3 +110,3 @@ | ||
nextElement = nextElement[property]; | ||
} while (nextElement && !isValidInput(nextElement)); | ||
} while (nextElement && !isInternalInput(nextElement)); | ||
@@ -485,16 +486,22 @@ return nextElement; | ||
var maxDetail = this.props.maxDetail; | ||
var options = { | ||
hour: 'numeric' | ||
}; | ||
var level = allViews.indexOf(maxDetail); | ||
if (level >= 1) { | ||
options.minute = 'numeric'; | ||
} | ||
var formatterOptions = getFormatterOptionsCache[level] || function () { | ||
var options = { | ||
hour: 'numeric' | ||
}; | ||
if (level >= 2) { | ||
options.second = 'numeric'; | ||
} | ||
if (level >= 1) { | ||
options.minute = 'numeric'; | ||
} | ||
return (0, _dateFormatter.getFormatter)(options); | ||
if (level >= 2) { | ||
options.second = 'numeric'; | ||
} | ||
getFormatterOptionsCache[level] = options; | ||
return options; | ||
}(); | ||
return (0, _dateFormatter.getFormatter)(formatterOptions); | ||
} | ||
@@ -501,0 +508,0 @@ }, { |
@@ -45,2 +45,3 @@ "use strict"; | ||
onChange = _ref.onChange, | ||
onKeyDown = _ref.onKeyDown, | ||
required = _ref.required, | ||
@@ -65,2 +66,3 @@ value = _ref.value; | ||
onChange: onChange, | ||
onKeyDown: onKeyDown, | ||
ref: inputRef, | ||
@@ -89,4 +91,5 @@ required: required, | ||
onChange: _propTypes["default"].func, | ||
onKeyDown: _propTypes["default"].func, | ||
required: _propTypes["default"].bool, | ||
value: _propTypes["default"].oneOf(['am', 'pm']) | ||
}; |
@@ -26,3 +26,3 @@ "use strict"; | ||
function _extends() { _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; }; return _extends.apply(this, arguments); } | ||
function _extends() { _extends = Object.assign ? Object.assign.bind() : 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; }; return _extends.apply(this, arguments); } | ||
@@ -29,0 +29,0 @@ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } |
@@ -24,3 +24,3 @@ "use strict"; | ||
function _extends() { _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; }; return _extends.apply(this, arguments); } | ||
function _extends() { _extends = Object.assign ? Object.assign.bind() : 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; }; return _extends.apply(this, arguments); } | ||
@@ -27,0 +27,0 @@ function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } |
@@ -10,3 +10,3 @@ "use strict"; | ||
var _react = _interopRequireDefault(require("react")); | ||
var _react = _interopRequireWildcard(require("react")); | ||
@@ -17,4 +17,2 @@ var _propTypes = _interopRequireDefault(require("prop-types")); | ||
var _mergeRefs = _interopRequireDefault(require("merge-refs")); | ||
var _updateInputWidth = _interopRequireWildcard(require("update-input-width")); | ||
@@ -24,2 +22,4 @@ | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } | ||
@@ -29,4 +29,2 @@ | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
/* eslint-disable jsx-a11y/no-autofocus */ | ||
@@ -48,2 +46,14 @@ var isIEOrEdgeLegacy = typeof window !== 'undefined' && /(MSIE|Trident\/|Edge\/)/.test(window.navigator.userAgent); | ||
function updateInputWidthOnLoad(element) { | ||
if (document.readyState === 'complete') { | ||
return; | ||
} | ||
function onLoad() { | ||
(0, _updateInputWidth["default"])(element); | ||
} | ||
window.addEventListener('load', onLoad); | ||
} | ||
function updateInputWidthOnFontLoad(element) { | ||
@@ -131,2 +141,11 @@ if (!document.fonts) { | ||
value = _ref.value; | ||
(0, _react.useLayoutEffect)(function () { | ||
if (!inputRef || !inputRef.current) { | ||
return; | ||
} | ||
(0, _updateInputWidth["default"])(inputRef.current); | ||
updateInputWidthOnLoad(inputRef.current); | ||
updateInputWidthOnFontLoad(inputRef.current); | ||
}, [inputRef, value]); | ||
var hasLeadingZero = showLeadingZeros && value && value < 10 && (value === '0' || !value.toString().startsWith('0')); | ||
@@ -161,3 +180,3 @@ var maxLength = max ? max.toString().length : null; | ||
placeholder: placeholder, | ||
ref: (0, _mergeRefs["default"])(_updateInputWidth["default"], updateInputWidthOnFontLoad, inputRef), | ||
ref: inputRef, | ||
required: required, | ||
@@ -164,0 +183,0 @@ step: step, |
@@ -24,3 +24,3 @@ "use strict"; | ||
function _extends() { _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; }; return _extends.apply(this, arguments); } | ||
function _extends() { _extends = Object.assign ? Object.assign.bind() : 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; }; return _extends.apply(this, arguments); } | ||
@@ -27,0 +27,0 @@ function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } |
@@ -24,3 +24,3 @@ "use strict"; | ||
function _extends() { _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; }; return _extends.apply(this, arguments); } | ||
function _extends() { _extends = Object.assign ? Object.assign.bind() : 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; }; return _extends.apply(this, arguments); } | ||
@@ -27,0 +27,0 @@ function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } |
@@ -12,2 +12,4 @@ "use strict"; | ||
var _reactDom = require("react-dom"); | ||
var _propTypes = _interopRequireDefault(require("prop-types")); | ||
@@ -27,3 +29,3 @@ | ||
var _excluded = ["clockClassName", "className", "maxDetail", "onChange", "value"], | ||
var _excluded = ["clockClassName", "className", "maxDetail", "onChange", "portalContainer", "value"], | ||
_excluded2 = ["onChange"]; | ||
@@ -41,3 +43,3 @@ | ||
function _extends() { _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; }; return _extends.apply(this, arguments); } | ||
function _extends() { _extends = Object.assign ? Object.assign.bind() : 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; }; return _extends.apply(this, arguments); } | ||
@@ -64,3 +66,3 @@ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } | ||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | ||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | ||
@@ -75,3 +77,3 @@ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } | ||
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | ||
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | ||
@@ -102,7 +104,15 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
_defineProperty(_assertThisInitialized(_this), "wrapper", /*#__PURE__*/(0, _react.createRef)()); | ||
_defineProperty(_assertThisInitialized(_this), "clockWrapper", /*#__PURE__*/(0, _react.createRef)()); | ||
_defineProperty(_assertThisInitialized(_this), "onOutsideAction", function (event) { | ||
// Try event.composedPath first to handle clicks inside a Shadow DOM. | ||
var _assertThisInitialize = _assertThisInitialized(_this), | ||
wrapper = _assertThisInitialize.wrapper, | ||
clockWrapper = _assertThisInitialize.clockWrapper; // Try event.composedPath first to handle clicks inside a Shadow DOM. | ||
var target = 'composedPath' in event ? event.composedPath()[0] : event.target; | ||
if (_this.wrapper && !_this.wrapper.contains(target)) { | ||
if (wrapper.current && !wrapper.current.contains(target) && (!clockWrapper.current || !clockWrapper.current.contains(target))) { | ||
_this.closeClock(); | ||
@@ -141,3 +151,3 @@ } | ||
if (openClockOnFocus) { | ||
if (event.target.getAttribute('data-select') === 'true') { | ||
if (event.target.dataset.select === 'true') { | ||
return; | ||
@@ -330,2 +340,3 @@ } | ||
onChange = _this$props4.onChange, | ||
portalContainer = _this$props4.portalContainer, | ||
value = _this$props4.value, | ||
@@ -335,2 +346,3 @@ clockProps = _objectWithoutProperties(_this$props4, _excluded); | ||
var className = "".concat(baseClassName, "__clock"); | ||
var classNames = (0, _mergeClassNames["default"])(className, "".concat(className, "--").concat(isOpen ? 'open' : 'closed')); | ||
@@ -342,3 +354,14 @@ var _concat3 = [].concat(value), | ||
var maxDetailIndex = allViews.indexOf(maxDetail); | ||
return /*#__PURE__*/_react["default"].createElement(_reactFit["default"], null, /*#__PURE__*/_react["default"].createElement("div", { | ||
var clock = /*#__PURE__*/_react["default"].createElement(_reactClock["default"], _extends({ | ||
className: clockClassName, | ||
renderMinuteHand: maxDetailIndex > 0, | ||
renderSecondHand: maxDetailIndex > 1, | ||
value: valueFrom | ||
}, clockProps)); | ||
return portalContainer ? /*#__PURE__*/(0, _reactDom.createPortal)( /*#__PURE__*/_react["default"].createElement("div", { | ||
ref: this.clockWrapper, | ||
className: classNames | ||
}, clock), portalContainer) : /*#__PURE__*/_react["default"].createElement(_reactFit["default"], null, /*#__PURE__*/_react["default"].createElement("div", { | ||
ref: function ref(_ref) { | ||
@@ -349,9 +372,4 @@ if (_ref && !isOpen) { | ||
}, | ||
className: (0, _mergeClassNames["default"])(className, "".concat(className, "--").concat(isOpen ? 'open' : 'closed')) | ||
}, /*#__PURE__*/_react["default"].createElement(_reactClock["default"], _extends({ | ||
className: clockClassName, | ||
renderMinuteHand: maxDetailIndex > 0, | ||
renderSecondHand: maxDetailIndex > 1, | ||
value: valueFrom | ||
}, clockProps)))); | ||
className: classNames | ||
}, clock)); | ||
} | ||
@@ -361,4 +379,2 @@ }, { | ||
value: function render() { | ||
var _this3 = this; | ||
var eventProps = this.eventProps; | ||
@@ -377,9 +393,3 @@ var _this$props5 = this.props, | ||
onFocus: this.onFocus, | ||
ref: function ref(_ref2) { | ||
if (!_ref2) { | ||
return; | ||
} | ||
_this3.wrapper = _ref2; | ||
} | ||
ref: this.wrapper | ||
}), this.renderInputs(), this.renderClock()); | ||
@@ -479,2 +489,3 @@ } | ||
openClockOnFocus: _propTypes["default"].bool, | ||
portalContainer: _propTypes["default"].object, | ||
required: _propTypes["default"].bool, | ||
@@ -481,0 +492,0 @@ secondAriaLabel: _propTypes["default"].string, |
{ | ||
"name": "react-time-picker", | ||
"version": "4.5.0", | ||
"version": "5.0.0", | ||
"description": "A time picker for your React app.", | ||
@@ -33,5 +33,4 @@ "main": "dist/entry.js", | ||
"merge-class-names": "^1.1.1", | ||
"merge-refs": "^1.0.0", | ||
"prop-types": "^15.6.0", | ||
"react-clock": "^3.0.0", | ||
"react-clock": "^3.1.0", | ||
"react-fit": "^1.4.0", | ||
@@ -45,8 +44,9 @@ "update-input-width": "^1.2.2" | ||
"@babel/preset-react": "^7.14.0", | ||
"@wojtekmaj/enzyme-adapter-react-17": "^0.6.0", | ||
"enzyme": "^3.10.0", | ||
"@testing-library/jest-dom": "^5.15.0", | ||
"@testing-library/react": "^12.1.0", | ||
"eslint": "^8.5.0", | ||
"eslint-config-wojtekmaj": "^0.6.5", | ||
"husky": "^7.0.0", | ||
"jest": "^27.0.0", | ||
"husky": "^8.0.0", | ||
"jest": "^29.0.0", | ||
"jest-environment-jsdom": "^29.0.0", | ||
"less": "^4.0.0", | ||
@@ -60,4 +60,4 @@ "prettier": "^2.5.0", | ||
"peerDependencies": { | ||
"react": "^16.3.0 || ^17.0.0 || ^18.0.0", | ||
"react-dom": "^16.3.0 || ^17.0.0 || ^18.0.0" | ||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0", | ||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" | ||
}, | ||
@@ -64,0 +64,0 @@ "resolutions": { |
@@ -70,2 +70,6 @@ [![npm](https://img.shields.io/npm/v/react-time-picker.svg)](https://www.npmjs.com/package/react-time-picker) ![downloads](https://img.shields.io/npm/dt/react-time-picker.svg) [![CI](https://github.com/wojtekmaj/react-time-picker/workflows/CI/badge.svg)](https://github.com/wojtekmaj/react-time-picker/actions) ![dependencies](https://img.shields.io/david/wojtekmaj/react-time-picker.svg) ![dev dependencies](https://img.shields.io/david/dev/wojtekmaj/react-time-picker.svg) [![tested with jest](https://img.shields.io/badge/tested_with-jest-99424f.svg)](https://github.com/facebook/jest) | ||
### Next.js and Vite | ||
Next.js and Vite do not allow components from `node_modules` to import styles. You'll need to follow instructions from [Custom styling](#custom-styling) to get going. | ||
## User guide | ||
@@ -108,2 +112,3 @@ | ||
| openClockOnFocus | Whether to open the clock on input focus. | `true` | `false` | | ||
| portalContainer | Element to render the clock in using portal. | n/a | `document.getElementById('my-div')` | | ||
| required | Whether date input should be required. | `false` | `true` | | ||
@@ -110,0 +115,0 @@ | secondAriaLabel | `aria-label` for the second input. | n/a | `"Second"` | |
@@ -24,2 +24,4 @@ import React, { createRef, PureComponent } from 'react'; | ||
const getFormatterOptionsCache = {}; | ||
const allViews = ['hour', 'minute', 'second']; | ||
@@ -33,4 +35,4 @@ | ||
function isValidInput(element) { | ||
return element.tagName === 'INPUT' && element.type === 'number'; | ||
function isInternalInput(element) { | ||
return element.dataset.input === 'true'; | ||
} | ||
@@ -42,3 +44,3 @@ | ||
nextElement = nextElement[property]; | ||
} while (nextElement && !isValidInput(nextElement)); | ||
} while (nextElement && !isInternalInput(nextElement)); | ||
return nextElement; | ||
@@ -153,12 +155,20 @@ } | ||
const options = { hour: 'numeric' }; | ||
const level = allViews.indexOf(maxDetail); | ||
if (level >= 1) { | ||
options.minute = 'numeric'; | ||
} | ||
if (level >= 2) { | ||
options.second = 'numeric'; | ||
} | ||
const formatterOptions = | ||
getFormatterOptionsCache[level] || | ||
(() => { | ||
const options = { hour: 'numeric' }; | ||
if (level >= 1) { | ||
options.minute = 'numeric'; | ||
} | ||
if (level >= 2) { | ||
options.second = 'numeric'; | ||
} | ||
return getFormatter(options); | ||
getFormatterOptionsCache[level] = options; | ||
return options; | ||
})(); | ||
return getFormatter(formatterOptions); | ||
} | ||
@@ -165,0 +175,0 @@ |
import React from 'react'; | ||
import { mount } from 'enzyme'; | ||
import { fireEvent, render } from '@testing-library/react'; | ||
@@ -12,3 +12,3 @@ import TimeInput from './TimeInput'; | ||
const formatter = new Intl.DateTimeFormat('de-DE', { hour: 'numeric' }); | ||
return formatter.format(date) === '21'; | ||
return formatter.format(date).includes('21'); | ||
} catch (err) { | ||
@@ -42,22 +42,9 @@ return false; | ||
let container; | ||
beforeEach(() => { | ||
container = document.createElement('div'); | ||
container.id = 'container'; | ||
document.body.appendChild(container); | ||
}); | ||
afterEach(() => { | ||
document.body.removeChild(container); | ||
container = null; | ||
}); | ||
it('renders a native input and custom inputs', () => { | ||
const component = mount(<TimeInput {...defaultProps} />); | ||
const { container } = render(<TimeInput {...defaultProps} />); | ||
const nativeInput = component.find('input[type="time"]'); | ||
const customInputs = component.find('input[data-input]'); | ||
const nativeInput = container.querySelector('input[type="time"]'); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
expect(nativeInput).toHaveLength(1); | ||
expect(nativeInput).toBeInTheDocument(); | ||
expect(customInputs).toHaveLength(2); | ||
@@ -67,27 +54,27 @@ }); | ||
it('does not render second input when maxDetail is "minute" or less', () => { | ||
const component = mount(<TimeInput {...defaultProps} maxDetail="minute" />); | ||
const { container } = render(<TimeInput {...defaultProps} maxDetail="minute" />); | ||
const customInputs = component.find('input[data-input]'); | ||
const secondInput = customInputs.find('input[name="second"]'); | ||
const minuteInput = customInputs.find('input[name="minute"]'); | ||
const hourInput = customInputs.find('input[name^="hour"]'); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
const secondInput = container.querySelector('input[name="second"]'); | ||
const minuteInput = container.querySelector('input[name="minute"]'); | ||
const hourInput = container.querySelector('input[name^="hour"]'); | ||
expect(customInputs).toHaveLength(2); | ||
expect(secondInput).toHaveLength(0); | ||
expect(minuteInput).toHaveLength(1); | ||
expect(hourInput).toHaveLength(1); | ||
expect(secondInput).toBeFalsy(); | ||
expect(minuteInput).toBeInTheDocument(); | ||
expect(hourInput).toBeInTheDocument(); | ||
}); | ||
it('does not render second and minute inputs when maxDetail is "hour" or less', () => { | ||
const component = mount(<TimeInput {...defaultProps} maxDetail="hour" />); | ||
const { container } = render(<TimeInput {...defaultProps} maxDetail="hour" />); | ||
const customInputs = component.find('input[data-input]'); | ||
const secondInput = customInputs.find('input[name="second"]'); | ||
const minuteInput = customInputs.find('input[name="minute"]'); | ||
const hourInput = customInputs.find('input[name^="hour"]'); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
const secondInput = container.querySelector('input[name="second"]'); | ||
const minuteInput = container.querySelector('input[name="minute"]'); | ||
const hourInput = container.querySelector('input[name^="hour"]'); | ||
expect(customInputs).toHaveLength(1); | ||
expect(secondInput).toHaveLength(0); | ||
expect(minuteInput).toHaveLength(0); | ||
expect(hourInput).toHaveLength(1); | ||
expect(secondInput).toBeFalsy(); | ||
expect(minuteInput).toBeFalsy(); | ||
expect(hourInput).toBeInTheDocument(); | ||
}); | ||
@@ -98,11 +85,11 @@ | ||
const component = mount(<TimeInput {...defaultProps} maxDetail="second" value={date} />); | ||
const { container } = render(<TimeInput {...defaultProps} maxDetail="second" value={date} />); | ||
const nativeInput = component.find('input[type="time"]'); | ||
const customInputs = component.find('input[data-input]'); | ||
const nativeInput = container.querySelector('input[type="time"]'); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
expect(nativeInput.prop('value')).toBe(date); | ||
expect(customInputs.at(0).prop('value')).toBe('10'); | ||
expect(customInputs.at(1).prop('value')).toBe('17'); | ||
expect(customInputs.at(2).prop('value')).toBe('0'); | ||
expect(nativeInput).toHaveValue(date); | ||
expect(customInputs[0]).toHaveValue(10); | ||
expect(customInputs[1]).toHaveValue(17); | ||
expect(customInputs[2]).toHaveValue(0); | ||
}); | ||
@@ -113,25 +100,25 @@ | ||
const component = mount( | ||
const { container } = render( | ||
<TimeInput {...defaultProps} locale="de-DE" maxDetail="second" value={date} />, | ||
); | ||
const nativeInput = component.find('input[type="time"]'); | ||
const customInputs = component.find('input[data-input]'); | ||
const nativeInput = container.querySelector('input[type="time"]'); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
expect(nativeInput.prop('value')).toBe(date); | ||
expect(customInputs.at(0).prop('value')).toBe('22'); | ||
expect(customInputs.at(1).prop('value')).toBe('17'); | ||
expect(customInputs.at(2).prop('value')).toBe('0'); | ||
expect(nativeInput).toHaveValue(date); | ||
expect(customInputs[0]).toHaveValue(22); | ||
expect(customInputs[1]).toHaveValue(17); | ||
expect(customInputs[2]).toHaveValue(0); | ||
}); | ||
it('shows empty value in all inputs correctly given null', () => { | ||
const component = mount(<TimeInput {...defaultProps} maxDetail="second" value={null} />); | ||
const { container } = render(<TimeInput {...defaultProps} maxDetail="second" value={null} />); | ||
const nativeInput = component.find('input[type="time"]'); | ||
const customInputs = component.find('input[data-input]'); | ||
const nativeInput = container.querySelector('input[type="time"]'); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
expect(nativeInput.prop('value')).toBeFalsy(); | ||
expect(customInputs.at(0).prop('value')).toBeFalsy(); | ||
expect(customInputs.at(1).prop('value')).toBeFalsy(); | ||
expect(customInputs.at(2).prop('value')).toBeFalsy(); | ||
expect(nativeInput).toHaveAttribute('value', ''); | ||
expect(customInputs[0]).toHaveAttribute('value', ''); | ||
expect(customInputs[1]).toHaveAttribute('value', ''); | ||
expect(customInputs[2]).toHaveAttribute('value', ''); | ||
}); | ||
@@ -142,67 +129,51 @@ | ||
const component = mount(<TimeInput {...defaultProps} maxDetail="second" value={date} />); | ||
const { container, rerender } = render( | ||
<TimeInput {...defaultProps} maxDetail="second" value={date} />, | ||
); | ||
component.setProps({ value: null }); | ||
rerender(<TimeInput {...defaultProps} maxDetail="second" value={null} />); | ||
const nativeInput = component.find('input[type="time"]'); | ||
const customInputs = component.find('input[data-input]'); | ||
const nativeInput = container.querySelector('input[type="time"]'); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
expect(nativeInput.prop('value')).toBeFalsy(); | ||
expect(customInputs.at(0).prop('value')).toBeFalsy(); | ||
expect(customInputs.at(1).prop('value')).toBeFalsy(); | ||
expect(customInputs.at(2).prop('value')).toBeFalsy(); | ||
expect(nativeInput).toHaveAttribute('value', ''); | ||
expect(customInputs[0]).toHaveAttribute('value', ''); | ||
expect(customInputs[1]).toHaveAttribute('value', ''); | ||
expect(customInputs[2]).toHaveAttribute('value', ''); | ||
}); | ||
it('renders custom inputs in a proper order (12-hour format)', () => { | ||
const component = mount(<TimeInput {...defaultProps} maxDetail="second" />); | ||
const { container } = render(<TimeInput {...defaultProps} maxDetail="second" />); | ||
const customInputs = component.find('input[data-input]'); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
expect(customInputs.at(0).prop('name')).toBe('hour12'); | ||
expect(customInputs.at(1).prop('name')).toBe('minute'); | ||
expect(customInputs.at(2).prop('name')).toBe('second'); | ||
expect(customInputs[0]).toHaveAttribute('name', 'hour12'); | ||
expect(customInputs[1]).toHaveAttribute('name', 'minute'); | ||
expect(customInputs[2]).toHaveAttribute('name', 'second'); | ||
}); | ||
itIfFullICU('renders custom inputs in a proper order (24-hour format)', () => { | ||
const component = mount(<TimeInput {...defaultProps} locale="de-DE" maxDetail="second" />); | ||
const { container } = render(<TimeInput {...defaultProps} locale="de-DE" maxDetail="second" />); | ||
const customInputs = component.find('input[data-input]'); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
expect(customInputs.at(0).prop('name')).toBe('hour24'); | ||
expect(customInputs.at(1).prop('name')).toBe('minute'); | ||
expect(customInputs.at(2).prop('name')).toBe('second'); | ||
expect(customInputs[0]).toHaveAttribute('name', 'hour24'); | ||
expect(customInputs[1]).toHaveAttribute('name', 'minute'); | ||
expect(customInputs[2]).toHaveAttribute('name', 'second'); | ||
}); | ||
it('renders hour input without leading zero by default', () => { | ||
const component = mount(<TimeInput {...defaultProps} maxDetail="second" />); | ||
it.todo('renders hour input without leading zero by default'); | ||
const hourInput = component.find('Hour12Input'); | ||
it.todo('renders minute input with leading zero by default'); | ||
expect(hourInput.prop('showLeadingZeros')).toBeFalsy(); | ||
}); | ||
it.todo('renders second input with leading zero by default'); | ||
it('renders minute input with leading zero by default', () => { | ||
const component = mount(<TimeInput {...defaultProps} maxDetail="second" />); | ||
const minuteInput = component.find('MinuteInput'); | ||
expect(minuteInput.prop('showLeadingZeros')).toBeTruthy(); | ||
}); | ||
it('renders second input with leading zero by default', () => { | ||
const component = mount(<TimeInput {...defaultProps} maxDetail="second" />); | ||
const secondInput = component.find('SecondInput'); | ||
expect(secondInput.prop('showLeadingZeros')).toBeTruthy(); | ||
}); | ||
describe('renders custom input in a proper order given format', () => { | ||
it('renders "h" properly', () => { | ||
const component = mount(<TimeInput {...defaultProps} format="h" />); | ||
const { container } = render(<TimeInput {...defaultProps} format="h" />); | ||
const componentInput = component.find('Hour12Input'); | ||
const customInputs = component.find('input[data-input]'); | ||
const componentInput = container.querySelector('input[name="hour12"]'); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
expect(componentInput).toHaveLength(1); | ||
expect(componentInput).toBeInTheDocument(); | ||
expect(customInputs).toHaveLength(1); | ||
@@ -212,10 +183,9 @@ }); | ||
it('renders "hh" properly', () => { | ||
const component = mount(<TimeInput {...defaultProps} format="hh" />); | ||
const { container } = render(<TimeInput {...defaultProps} format="hh" />); | ||
const componentInput = component.find('Hour12Input'); | ||
const customInputs = component.find('input[data-input]'); | ||
const componentInput = container.querySelector('input[name="hour12"]'); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
expect(componentInput).toHaveLength(1); | ||
expect(componentInput).toBeInTheDocument(); | ||
expect(customInputs).toHaveLength(1); | ||
expect(componentInput.prop('showLeadingZeros')).toBeTruthy(); | ||
}); | ||
@@ -226,3 +196,3 @@ | ||
const renderComponent = () => mount(<TimeInput {...defaultProps} format="hhh" />); | ||
const renderComponent = () => render(<TimeInput {...defaultProps} format="hhh" />); | ||
@@ -235,8 +205,8 @@ expect(renderComponent).toThrow('Unsupported token: hhh'); | ||
it('renders "H" properly', () => { | ||
const component = mount(<TimeInput {...defaultProps} format="H" />); | ||
const { container } = render(<TimeInput {...defaultProps} format="H" />); | ||
const componentInput = component.find('Hour24Input'); | ||
const customInputs = component.find('input[data-input]'); | ||
const componentInput = container.querySelector('input[name="hour24"]'); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
expect(componentInput).toHaveLength(1); | ||
expect(componentInput).toBeInTheDocument(); | ||
expect(customInputs).toHaveLength(1); | ||
@@ -246,10 +216,9 @@ }); | ||
it('renders "HH" properly', () => { | ||
const component = mount(<TimeInput {...defaultProps} format="HH" />); | ||
const { container } = render(<TimeInput {...defaultProps} format="HH" />); | ||
const componentInput = component.find('Hour24Input'); | ||
const customInputs = component.find('input[data-input]'); | ||
const componentInput = container.querySelector('input[name="hour24"]'); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
expect(componentInput).toHaveLength(1); | ||
expect(componentInput).toBeInTheDocument(); | ||
expect(customInputs).toHaveLength(1); | ||
expect(componentInput.prop('showLeadingZeros')).toBeTruthy(); | ||
}); | ||
@@ -260,3 +229,3 @@ | ||
const renderComponent = () => mount(<TimeInput {...defaultProps} format="HHH" />); | ||
const renderComponent = () => render(<TimeInput {...defaultProps} format="HHH" />); | ||
@@ -269,8 +238,8 @@ expect(renderComponent).toThrow('Unsupported token: HHH'); | ||
it('renders "m" properly', () => { | ||
const component = mount(<TimeInput {...defaultProps} format="m" />); | ||
const { container } = render(<TimeInput {...defaultProps} format="m" />); | ||
const componentInput = component.find('MinuteInput'); | ||
const customInputs = component.find('input[data-input]'); | ||
const componentInput = container.querySelector('input[name="minute"]'); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
expect(componentInput).toHaveLength(1); | ||
expect(componentInput).toBeInTheDocument(); | ||
expect(customInputs).toHaveLength(1); | ||
@@ -280,10 +249,9 @@ }); | ||
it('renders "mm" properly', () => { | ||
const component = mount(<TimeInput {...defaultProps} format="mm" />); | ||
const { container } = render(<TimeInput {...defaultProps} format="mm" />); | ||
const componentInput = component.find('MinuteInput'); | ||
const customInputs = component.find('input[data-input]'); | ||
const componentInput = container.querySelector('input[name="minute"]'); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
expect(componentInput).toHaveLength(1); | ||
expect(componentInput).toBeInTheDocument(); | ||
expect(customInputs).toHaveLength(1); | ||
expect(componentInput.prop('showLeadingZeros')).toBeTruthy(); | ||
}); | ||
@@ -294,3 +262,3 @@ | ||
const renderComponent = () => mount(<TimeInput {...defaultProps} format="mmm" />); | ||
const renderComponent = () => render(<TimeInput {...defaultProps} format="mmm" />); | ||
@@ -303,8 +271,8 @@ expect(renderComponent).toThrow('Unsupported token: mmm'); | ||
it('renders "s" properly', () => { | ||
const component = mount(<TimeInput {...defaultProps} format="s" />); | ||
const { container } = render(<TimeInput {...defaultProps} format="s" />); | ||
const componentInput = component.find('SecondInput'); | ||
const customInputs = component.find('input[data-input]'); | ||
const componentInput = container.querySelector('input[name="second"]'); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
expect(componentInput).toHaveLength(1); | ||
expect(componentInput).toBeInTheDocument(); | ||
expect(customInputs).toHaveLength(1); | ||
@@ -314,10 +282,9 @@ }); | ||
it('renders "ss" properly', () => { | ||
const component = mount(<TimeInput {...defaultProps} format="ss" />); | ||
const { container } = render(<TimeInput {...defaultProps} format="ss" />); | ||
const componentInput = component.find('SecondInput'); | ||
const customInputs = component.find('input[data-input]'); | ||
const componentInput = container.querySelector('input[name="second"]'); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
expect(componentInput).toHaveLength(1); | ||
expect(componentInput).toBeInTheDocument(); | ||
expect(customInputs).toHaveLength(1); | ||
expect(componentInput.prop('showLeadingZeros')).toBeTruthy(); | ||
}); | ||
@@ -328,3 +295,3 @@ | ||
const renderComponent = () => mount(<TimeInput {...defaultProps} format="sss" />); | ||
const renderComponent = () => render(<TimeInput {...defaultProps} format="sss" />); | ||
@@ -337,8 +304,8 @@ expect(renderComponent).toThrow('Unsupported token: sss'); | ||
it('renders "a" properly', () => { | ||
const component = mount(<TimeInput {...defaultProps} format="a" />); | ||
const { container } = render(<TimeInput {...defaultProps} format="a" />); | ||
const componentInput = component.find('AmPm'); | ||
const customInputs = component.find('input[data-input]'); | ||
const componentSelect = container.querySelector('select[name="amPm"]'); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
expect(componentInput).toHaveLength(1); | ||
expect(componentSelect).toBeInTheDocument(); | ||
expect(customInputs).toHaveLength(0); | ||
@@ -349,18 +316,18 @@ }); | ||
it('renders proper input separators', () => { | ||
const component = mount(<TimeInput {...defaultProps} maxDetail="second" />); | ||
const { container } = render(<TimeInput {...defaultProps} maxDetail="second" />); | ||
const separators = component.find('.react-time-picker__inputGroup__divider'); | ||
const separators = container.querySelectorAll('.react-time-picker__inputGroup__divider'); | ||
expect(separators).toHaveLength(3); | ||
expect(separators.at(0).text()).toBe(':'); | ||
expect(separators.at(1).text()).toBe(':'); | ||
expect(separators.at(2).text()).toBe(' '); | ||
expect(separators[0]).toHaveTextContent(':'); | ||
expect(separators[1]).toHaveTextContent(':'); | ||
expect(separators[2]).toHaveTextContent(''); // Non-breaking space | ||
}); | ||
it('renders proper amount of separators', () => { | ||
const component = mount(<TimeInput {...defaultProps} />); | ||
const { container } = render(<TimeInput {...defaultProps} />); | ||
const separators = component.find('.react-time-picker__inputGroup__divider'); | ||
const customInputs = component.find('input[data-input]'); | ||
const ampm = component.find('select'); | ||
const separators = container.querySelectorAll('.react-time-picker__inputGroup__divider'); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
const ampm = container.querySelectorAll('select'); | ||
@@ -371,132 +338,137 @@ expect(separators).toHaveLength(customInputs.length + ampm.length - 1); | ||
it('jumps to the next field when right arrow is pressed', () => { | ||
const component = mount(<TimeInput {...defaultProps} maxDetail="second" />, { | ||
const { container } = render(<TimeInput {...defaultProps} maxDetail="second" />, { | ||
attachTo: container, | ||
}); | ||
const customInputs = component.find('input[data-input]'); | ||
const hourInput = customInputs.at(0); | ||
const minuteInput = customInputs.at(1); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
const hourInput = customInputs[0]; | ||
const minuteInput = customInputs[1]; | ||
hourInput.getDOMNode().focus(); | ||
fireEvent.focus(hourInput); | ||
hourInput.focus(); | ||
expect(document.activeElement).toBe(hourInput.getDOMNode()); | ||
expect(hourInput).toHaveFocus(); | ||
hourInput.simulate('keydown', getKey('ArrowRight')); | ||
fireEvent.keyDown(hourInput, getKey('ArrowRight')); | ||
expect(document.activeElement).toBe(minuteInput.getDOMNode()); | ||
expect(minuteInput).toHaveFocus(); | ||
}); | ||
it('jumps to the next field when separator key is pressed', () => { | ||
const component = mount(<TimeInput {...defaultProps} maxDetail="second" />, { | ||
const { container } = render(<TimeInput {...defaultProps} maxDetail="second" />, { | ||
attachTo: container, | ||
}); | ||
const customInputs = component.find('input[data-input]'); | ||
const hourInput = customInputs.at(0); | ||
const minuteInput = customInputs.at(1); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
const hourInput = customInputs[0]; | ||
const minuteInput = customInputs[1]; | ||
hourInput.getDOMNode().focus(); | ||
fireEvent.focus(hourInput); | ||
hourInput.focus(); | ||
expect(document.activeElement).toBe(hourInput.getDOMNode()); | ||
expect(hourInput).toHaveFocus(); | ||
const separators = component.find('.react-time-picker__inputGroup__divider'); | ||
const separatorKey = separators.at(0).text(); | ||
hourInput.simulate('keydown', getKey(separatorKey)); | ||
const separators = container.querySelectorAll('.react-time-picker__inputGroup__divider'); | ||
const separatorKey = separators[0].textContent; | ||
fireEvent.keyDown(hourInput, getKey(separatorKey)); | ||
expect(document.activeElement).toBe(minuteInput.getDOMNode()); | ||
expect(minuteInput).toHaveFocus(); | ||
}); | ||
it('does not jump to the next field when right arrow is pressed when the last input is focused', () => { | ||
const component = mount(<TimeInput {...defaultProps} maxDetail="second" />, { | ||
const { container } = render(<TimeInput {...defaultProps} maxDetail="second" />, { | ||
attachTo: container, | ||
}); | ||
const select = component.find('select'); | ||
const select = container.querySelector('select'); | ||
select.getDOMNode().focus(); | ||
select.focus(); | ||
expect(document.activeElement).toBe(select.getDOMNode()); | ||
expect(select).toHaveFocus(); | ||
select.simulate('keydown', getKey('ArrowRight')); | ||
fireEvent.keyDown(select, getKey('ArrowRight')); | ||
expect(document.activeElement).toBe(select.getDOMNode()); | ||
expect(select).toHaveFocus(); | ||
}); | ||
it('jumps to the previous field when left arrow is pressed', () => { | ||
const component = mount(<TimeInput {...defaultProps} maxDetail="second" />, { | ||
const { container } = render(<TimeInput {...defaultProps} maxDetail="second" />, { | ||
attachTo: container, | ||
}); | ||
const customInputs = component.find('input[data-input]'); | ||
const hourInput = customInputs.at(0); | ||
const minuteInput = customInputs.at(1); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
const hourInput = customInputs[0]; | ||
const minuteInput = customInputs[1]; | ||
minuteInput.getDOMNode().focus(); | ||
fireEvent.focus(minuteInput); | ||
minuteInput.focus(); | ||
expect(document.activeElement).toBe(minuteInput.getDOMNode()); | ||
expect(minuteInput).toHaveFocus(); | ||
minuteInput.simulate('keydown', getKey('ArrowLeft')); | ||
fireEvent.keyDown(minuteInput, getKey('ArrowLeft')); | ||
expect(document.activeElement).toBe(hourInput.getDOMNode()); | ||
expect(hourInput).toHaveFocus(); | ||
}); | ||
it('does not jump to the previous field when left arrow is pressed when the first input is focused', () => { | ||
const component = mount(<TimeInput {...defaultProps} maxDetail="second" />, { | ||
const { container } = render(<TimeInput {...defaultProps} maxDetail="second" />, { | ||
attachTo: container, | ||
}); | ||
const customInputs = component.find('input[data-input]'); | ||
const hourInput = customInputs.at(0); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
const hourInput = customInputs[0]; | ||
hourInput.getDOMNode().focus(); | ||
fireEvent.focus(hourInput); | ||
hourInput.focus(); | ||
expect(document.activeElement).toBe(hourInput.getDOMNode()); | ||
expect(hourInput).toHaveFocus(); | ||
hourInput.simulate('keydown', getKey('ArrowLeft')); | ||
fireEvent.keyDown(hourInput, getKey('ArrowLeft')); | ||
expect(document.activeElement).toBe(hourInput.getDOMNode()); | ||
expect(hourInput).toHaveFocus(); | ||
}); | ||
it("jumps to the next field when a value which can't be extended to another valid value is entered", () => { | ||
const component = mount(<TimeInput {...defaultProps} />, { attachTo: container }); | ||
const { container } = render(<TimeInput {...defaultProps} />, { attachTo: container }); | ||
const customInputs = component.find('input[data-input]'); | ||
const hourInput = customInputs.at(0); | ||
const minuteInput = customInputs.at(1); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
const hourInput = customInputs[0]; | ||
const minuteInput = customInputs[1]; | ||
hourInput.getDOMNode().focus(); | ||
hourInput.getDOMNode().value = '4'; | ||
fireEvent.focus(hourInput); | ||
hourInput.simulate('keyup', { target: hourInput.getDOMNode(), key: '4' }); | ||
hourInput.value = '4'; | ||
fireEvent.keyUp(hourInput, { key: '4' }); | ||
expect(document.activeElement).toBe(minuteInput.getDOMNode()); | ||
expect(minuteInput).toHaveFocus(); | ||
}); | ||
it('jumps to the next field when a value as long as the length of maximum value is entered', () => { | ||
const component = mount(<TimeInput {...defaultProps} />, { attachTo: container }); | ||
const { container } = render(<TimeInput {...defaultProps} />, { attachTo: container }); | ||
const customInputs = component.find('input[data-input]'); | ||
const hourInput = customInputs.at(0); | ||
const minuteInput = customInputs.at(1); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
const hourInput = customInputs[0]; | ||
const minuteInput = customInputs[1]; | ||
hourInput.getDOMNode().focus(); | ||
hourInput.getDOMNode().value = '02'; | ||
fireEvent.focus(hourInput); | ||
hourInput.simulate('keyup', { target: hourInput.getDOMNode(), key: '2' }); | ||
hourInput.value = '02'; | ||
fireEvent.keyUp(hourInput, { key: '2' }); | ||
expect(document.activeElement).toBe(minuteInput.getDOMNode()); | ||
expect(minuteInput).toHaveFocus(); | ||
}); | ||
it('does not jump the next field when a value which can be extended to another valid value is entered', () => { | ||
const component = mount(<TimeInput {...defaultProps} />, { attachTo: container }); | ||
const { container } = render(<TimeInput {...defaultProps} />, { attachTo: container }); | ||
const customInputs = component.find('input[data-input]'); | ||
const hourInput = customInputs.at(0); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
const hourInput = customInputs[0]; | ||
hourInput.getDOMNode().focus(); | ||
hourInput.getDOMNode().value = '1'; | ||
fireEvent.focus(hourInput); | ||
hourInput.focus(); | ||
hourInput.simulate('keyup', { target: hourInput.getDOMNode(), key: '1' }); | ||
hourInput.value = '1'; | ||
fireEvent.keyUp(hourInput, { key: '1' }); | ||
expect(document.activeElement).toBe(hourInput.getDOMNode()); | ||
expect(hourInput).toHaveFocus(); | ||
}); | ||
@@ -508,10 +480,9 @@ | ||
const component = mount( | ||
const { container } = render( | ||
<TimeInput {...defaultProps} maxDetail="second" onChange={onChange} value={date} />, | ||
); | ||
const customInputs = component.find('input[data-input]'); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
customInputs.at(0).getDOMNode().value = '20'; | ||
customInputs.at(0).simulate('change'); | ||
fireEvent.change(customInputs[0], { target: { value: '20' } }); | ||
@@ -522,15 +493,14 @@ expect(onChange).toHaveBeenCalled(); | ||
it.only('triggers onChange correctly when cleared custom inputs', () => { | ||
it('triggers onChange correctly when cleared custom inputs', () => { | ||
const onChange = jest.fn(); | ||
const date = '22:17:00'; | ||
const component = mount( | ||
const { container } = render( | ||
<TimeInput {...defaultProps} maxDetail="second" onChange={onChange} value={date} />, | ||
); | ||
const customInputs = component.find('input[data-input]'); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
customInputs.forEach((customInput) => { | ||
customInput.getDOMNode().value = ''; | ||
customInput.simulate('change'); | ||
fireEvent.change(customInput, { target: { value: '' } }); | ||
}); | ||
@@ -546,10 +516,9 @@ | ||
const component = mount( | ||
const { container } = render( | ||
<TimeInput {...defaultProps} maxDetail="second" onChange={onChange} value={date} />, | ||
); | ||
const nativeInput = component.find('input[type="time"]'); | ||
const nativeInput = container.querySelector('input[type="time"]'); | ||
nativeInput.getDOMNode().value = '20:17:00'; | ||
nativeInput.simulate('change'); | ||
fireEvent.change(nativeInput, { target: { value: '20:17:00' } }); | ||
@@ -564,10 +533,9 @@ expect(onChange).toHaveBeenCalled(); | ||
const component = mount( | ||
const { container } = render( | ||
<TimeInput {...defaultProps} maxDetail="second" onChange={onChange} value={date} />, | ||
); | ||
const nativeInput = component.find('input[type="time"]'); | ||
const nativeInput = container.querySelector('input[type="time"]'); | ||
nativeInput.getDOMNode().value = ''; | ||
nativeInput.simulate('change'); | ||
fireEvent.change(nativeInput, { target: { value: '' } }); | ||
@@ -574,0 +542,0 @@ expect(onChange).toHaveBeenCalled(); |
@@ -19,2 +19,3 @@ import React from 'react'; | ||
onChange, | ||
onKeyDown, | ||
required, | ||
@@ -38,2 +39,3 @@ value, | ||
onChange={onChange} | ||
onKeyDown={onKeyDown} | ||
ref={inputRef} | ||
@@ -63,4 +65,5 @@ required={required} | ||
onChange: PropTypes.func, | ||
onKeyDown: PropTypes.func, | ||
required: PropTypes.bool, | ||
value: PropTypes.oneOf(['am', 'pm']), | ||
}; |
import React from 'react'; | ||
import { shallow } from 'enzyme'; | ||
import { render } from '@testing-library/react'; | ||
@@ -13,8 +13,8 @@ import AmPm from './AmPm'; | ||
it('renders a select', () => { | ||
const component = shallow(<AmPm {...defaultProps} />); | ||
const { container } = render(<AmPm {...defaultProps} />); | ||
const select = component.find('select'); | ||
const options = select.find('option'); | ||
const select = container.querySelector('select'); | ||
expect(select).toBeInTheDocument(); | ||
expect(select).toHaveLength(1); | ||
const options = select.querySelectorAll('option'); | ||
expect(options).toHaveLength(3); | ||
@@ -26,15 +26,15 @@ }); | ||
const component = shallow(<AmPm {...defaultProps} ariaLabel={amPmAriaLabel} />); | ||
const { container } = render(<AmPm {...defaultProps} ariaLabel={amPmAriaLabel} />); | ||
const select = component.find('select'); | ||
const select = container.querySelector('select'); | ||
expect(select.prop('aria-label')).toBe(amPmAriaLabel); | ||
expect(select).toHaveAttribute('aria-label', amPmAriaLabel); | ||
}); | ||
it('has proper name defined', () => { | ||
const component = shallow(<AmPm {...defaultProps} />); | ||
const { container } = render(<AmPm {...defaultProps} />); | ||
const select = component.find('select'); | ||
const select = container.querySelector('select'); | ||
expect(select.prop('name')).toBe('amPm'); | ||
expect(select).toHaveAttribute('name', 'amPm'); | ||
}); | ||
@@ -45,8 +45,8 @@ | ||
const component = shallow(<AmPm {...defaultProps} className={className} />); | ||
const { container } = render(<AmPm {...defaultProps} className={className} />); | ||
const select = component.find('select'); | ||
const select = container.querySelector('select'); | ||
expect(select.hasClass('react-time-picker__input')).toBe(true); | ||
expect(select.hasClass('react-time-picker__amPm')).toBe(true); | ||
expect(select).toHaveClass('react-time-picker__input'); | ||
expect(select).toHaveClass('react-time-picker__amPm'); | ||
}); | ||
@@ -57,71 +57,71 @@ | ||
const component = shallow(<AmPm {...defaultProps} value={value} />); | ||
const { container } = render(<AmPm {...defaultProps} value={value} />); | ||
const select = component.find('select'); | ||
const select = container.querySelector('select'); | ||
expect(select.prop('value')).toBe(value); | ||
expect(select).toHaveValue(value); | ||
}); | ||
it('does not disable select by default', () => { | ||
const component = shallow(<AmPm {...defaultProps} />); | ||
const { container } = render(<AmPm {...defaultProps} />); | ||
const select = component.find('select'); | ||
const select = container.querySelector('select'); | ||
expect(select.prop('disabled')).toBeFalsy(); | ||
expect(select).not.toBeDisabled(); | ||
}); | ||
it('disables input given disabled flag', () => { | ||
const component = shallow(<AmPm {...defaultProps} disabled />); | ||
const { container } = render(<AmPm {...defaultProps} disabled />); | ||
const select = component.find('select'); | ||
const select = container.querySelector('select'); | ||
expect(select.prop('disabled')).toBeTruthy(); | ||
expect(select).toBeDisabled(); | ||
}); | ||
it('should not disable anything by default', () => { | ||
const component = shallow(<AmPm {...defaultProps} />); | ||
const { container } = render(<AmPm {...defaultProps} />); | ||
const select = component.find('select'); | ||
const optionAm = select.find('option[value="am"]'); | ||
const optionPm = select.find('option[value="pm"]'); | ||
const select = container.querySelector('select'); | ||
const optionAm = select.querySelector('option[value="am"]'); | ||
const optionPm = select.querySelector('option[value="pm"]'); | ||
expect(optionAm.prop('disabled')).toBeFalsy(); | ||
expect(optionPm.prop('disabled')).toBeFalsy(); | ||
expect(optionAm).not.toBeDisabled(); | ||
expect(optionPm).not.toBeDisabled(); | ||
}); | ||
it('should disable "pm" given maxTime before 12:00 pm', () => { | ||
const component = shallow(<AmPm {...defaultProps} maxTime="11:59" />); | ||
const { container } = render(<AmPm {...defaultProps} maxTime="11:59" />); | ||
const select = component.find('select'); | ||
const optionPm = select.find('option[value="pm"]'); | ||
const select = container.querySelector('select'); | ||
const optionPm = select.querySelector('option[value="pm"]'); | ||
expect(optionPm.prop('disabled')).toBeTruthy(); | ||
expect(optionPm).toBeDisabled(); | ||
}); | ||
it('should not disable "pm" given maxTime after or equal to 12:00 pm', () => { | ||
const component = shallow(<AmPm {...defaultProps} maxTime="12:00" />); | ||
const { container } = render(<AmPm {...defaultProps} maxTime="12:00" />); | ||
const select = component.find('select'); | ||
const optionPm = select.find('option[value="pm"]'); | ||
const select = container.querySelector('select'); | ||
const optionPm = select.querySelector('option[value="pm"]'); | ||
expect(optionPm.prop('disabled')).toBeFalsy(); | ||
expect(optionPm).not.toBeDisabled(); | ||
}); | ||
it('should disable "am" given minTime after or equal to 12:00 pm', () => { | ||
const component = shallow(<AmPm {...defaultProps} minTime="12:00" />); | ||
const { container } = render(<AmPm {...defaultProps} minTime="12:00" />); | ||
const select = component.find('select'); | ||
const optionAm = select.find('option[value="am"]'); | ||
const select = container.querySelector('select'); | ||
const optionAm = select.querySelector('option[value="am"]'); | ||
expect(optionAm.prop('disabled')).toBeTruthy(); | ||
expect(optionAm).toBeDisabled(); | ||
}); | ||
it('should not disable "am" given minTime before 12:00 pm', () => { | ||
const component = shallow(<AmPm {...defaultProps} minTime="11:59" />); | ||
const { container } = render(<AmPm {...defaultProps} minTime="11:59" />); | ||
const select = component.find('select'); | ||
const optionAm = select.find('option[value="pm"]'); | ||
const select = container.querySelector('select'); | ||
const optionAm = select.querySelector('option[value="pm"]'); | ||
expect(optionAm.prop('disabled')).toBeFalsy(); | ||
expect(optionAm).not.toBeDisabled(); | ||
}); | ||
}); |
import React from 'react'; | ||
import { mount } from 'enzyme'; | ||
import { render } from '@testing-library/react'; | ||
@@ -14,7 +14,7 @@ import Hour12Input from './Hour12Input'; | ||
it('renders an input', () => { | ||
const component = mount(<Hour12Input {...defaultProps} />); | ||
const { container } = render(<Hour12Input {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input).toHaveLength(1); | ||
expect(input).toBeInTheDocument(); | ||
}); | ||
@@ -25,7 +25,7 @@ | ||
const component = mount(<Hour12Input {...defaultProps} ariaLabel={hourAriaLabel} />); | ||
const { container } = render(<Hour12Input {...defaultProps} ariaLabel={hourAriaLabel} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('aria-label')).toBe(hourAriaLabel); | ||
expect(input).toHaveAttribute('aria-label', hourAriaLabel); | ||
}); | ||
@@ -36,46 +36,42 @@ | ||
const component = mount(<Hour12Input {...defaultProps} placeholder={hourPlaceholder} />); | ||
const { container } = render(<Hour12Input {...defaultProps} placeholder={hourPlaceholder} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('placeholder')).toBe(hourPlaceholder); | ||
expect(input).toHaveAttribute('placeholder', hourPlaceholder); | ||
}); | ||
it('renders "0" given showLeadingZeros if hour is <10', () => { | ||
const component = mount(<Hour12Input {...defaultProps} showLeadingZeros value="9" />); | ||
const { container } = render(<Hour12Input {...defaultProps} showLeadingZeros value="9" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(component.text()).toContain('0'); | ||
expect(input.prop('className')).toContain(`${defaultProps.className}__input--hasLeadingZero`); | ||
expect(container).toHaveTextContent('0'); | ||
expect(input).toHaveClass(`${defaultProps.className}__input--hasLeadingZero`); | ||
}); | ||
it('does not render "0" given showLeadingZeros if hour is >=10', () => { | ||
const component = mount(<Hour12Input {...defaultProps} showLeadingZeros value="10" />); | ||
const { container } = render(<Hour12Input {...defaultProps} showLeadingZeros value="10" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(component.text()).not.toContain('0'); | ||
expect(input.prop('className')).not.toContain( | ||
`${defaultProps.className}__input--hasLeadingZero`, | ||
); | ||
expect(container).not.toHaveTextContent('0'); | ||
expect(input).not.toHaveClass(`${defaultProps.className}__input--hasLeadingZero`); | ||
}); | ||
it('does not render "0" if not given showLeadingZeros', () => { | ||
const component = mount(<Hour12Input {...defaultProps} value="9" />); | ||
const { container } = render(<Hour12Input {...defaultProps} value="9" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(component.text()).not.toContain('0'); | ||
expect(input.prop('className')).not.toContain( | ||
`${defaultProps.className}__input--hasLeadingZero`, | ||
); | ||
expect(container).not.toHaveTextContent('0'); | ||
expect(input).not.toHaveClass(`${defaultProps.className}__input--hasLeadingZero`); | ||
}); | ||
it('has proper name defined', () => { | ||
const component = mount(<Hour12Input {...defaultProps} />); | ||
const { container } = render(<Hour12Input {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('name')).toBe('hour12'); | ||
expect(input).toHaveAttribute('name', 'hour12'); | ||
}); | ||
@@ -86,8 +82,8 @@ | ||
const component = mount(<Hour12Input {...defaultProps} className={className} />); | ||
const { container } = render(<Hour12Input {...defaultProps} className={className} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.hasClass('react-time-picker__input')).toBe(true); | ||
expect(input.hasClass('react-time-picker__hour')).toBe(true); | ||
expect(input).toHaveClass('react-time-picker__input'); | ||
expect(input).toHaveClass('react-time-picker__hour'); | ||
}); | ||
@@ -98,7 +94,7 @@ | ||
const component = mount(<Hour12Input {...defaultProps} value={value} />); | ||
const { container } = render(<Hour12Input {...defaultProps} value={value} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('value')).toBe(value); | ||
expect(input).toHaveValue(Number(value)); | ||
}); | ||
@@ -109,39 +105,39 @@ | ||
const component = mount(<Hour12Input {...defaultProps} value={value} />); | ||
const { container } = render(<Hour12Input {...defaultProps} value={value} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('value')).toBe(`${value - 12}`); | ||
expect(input).toHaveValue(value - 12); | ||
}); | ||
it('does not disable input by default', () => { | ||
const component = mount(<Hour12Input {...defaultProps} />); | ||
const { container } = render(<Hour12Input {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('disabled')).toBeFalsy(); | ||
expect(input).not.toBeDisabled(); | ||
}); | ||
it('disables input given disabled flag', () => { | ||
const component = mount(<Hour12Input {...defaultProps} disabled />); | ||
const { container } = render(<Hour12Input {...defaultProps} disabled />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('disabled')).toBeTruthy(); | ||
expect(input).toBeDisabled(); | ||
}); | ||
it('is not required input by default', () => { | ||
const component = mount(<Hour12Input {...defaultProps} />); | ||
const { container } = render(<Hour12Input {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('required')).toBeFalsy(); | ||
expect(input).not.toBeRequired(); | ||
}); | ||
it('required input given required flag', () => { | ||
const component = mount(<Hour12Input {...defaultProps} required />); | ||
const { container } = render(<Hour12Input {...defaultProps} required />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('required')).toBeTruthy(); | ||
expect(input).toBeRequired(); | ||
}); | ||
@@ -152,3 +148,3 @@ | ||
mount(<Hour12Input {...defaultProps} inputRef={inputRef} />); | ||
render(<Hour12Input {...defaultProps} inputRef={inputRef} />); | ||
@@ -159,105 +155,105 @@ expect(inputRef).toHaveBeenCalled(); | ||
it('has min = 1 by default', () => { | ||
const component = mount(<Hour12Input {...defaultProps} />); | ||
it('has min = "1" by default', () => { | ||
const { container } = render(<Hour12Input {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('min')).toBe(1); | ||
expect(input).toHaveAttribute('min', '1'); | ||
}); | ||
it('has min = (hour in minTime) given am minTime when amPm is am', () => { | ||
const component = mount(<Hour12Input {...defaultProps} amPm="am" minTime="5:35" />); | ||
const { container } = render(<Hour12Input {...defaultProps} amPm="am" minTime="5:35" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('min')).toBe(5); | ||
expect(input).toHaveAttribute('min', '5'); | ||
}); | ||
it('has min = (hour in minTime) given pm minTime when amPm is pm', () => { | ||
const component = mount(<Hour12Input {...defaultProps} amPm="pm" minTime="17:35" />); | ||
const { container } = render(<Hour12Input {...defaultProps} amPm="pm" minTime="17:35" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('min')).toBe(5); | ||
expect(input).toHaveAttribute('min', '5'); | ||
}); | ||
it('has min = 1 given am minTime when amPm is pm', () => { | ||
const component = mount(<Hour12Input {...defaultProps} amPm="pm" minTime="5:35" />); | ||
it('has min = "1" given am minTime when amPm is pm', () => { | ||
const { container } = render(<Hour12Input {...defaultProps} amPm="pm" minTime="5:35" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('min')).toBe(1); | ||
expect(input).toHaveAttribute('min', '1'); | ||
}); | ||
it('has min = 1 given pm minTime when amPm is am', () => { | ||
const component = mount(<Hour12Input {...defaultProps} amPm="am" minTime="17:35" />); | ||
it('has min = "1" given pm minTime when amPm is am', () => { | ||
const { container } = render(<Hour12Input {...defaultProps} amPm="am" minTime="17:35" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('min')).toBe(1); | ||
expect(input).toHaveAttribute('min', '1'); | ||
}); | ||
it('has min = 1 given 12 am minTime when amPm is am', () => { | ||
const component = mount(<Hour12Input {...defaultProps} amPm="am" minTime="00:35" />); | ||
it('has min = "1" given 12 am minTime when amPm is am', () => { | ||
const { container } = render(<Hour12Input {...defaultProps} amPm="am" minTime="00:35" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('min')).toBe(1); | ||
expect(input).toHaveAttribute('min', '1'); | ||
}); | ||
it('has min = 1 given 12 pm minTime when amPm is pm', () => { | ||
const component = mount(<Hour12Input {...defaultProps} amPm="pm" minTime="12:35" />); | ||
it('has min = "1" given 12 pm minTime when amPm is pm', () => { | ||
const { container } = render(<Hour12Input {...defaultProps} amPm="pm" minTime="12:35" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('min')).toBe(1); | ||
expect(input).toHaveAttribute('min', '1'); | ||
}); | ||
it('has max = 12 by default', () => { | ||
const component = mount(<Hour12Input {...defaultProps} />); | ||
it('has max = "12" by default', () => { | ||
const { container } = render(<Hour12Input {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('max')).toBe(12); | ||
expect(input).toHaveAttribute('max', '12'); | ||
}); | ||
it('has max = (hour in maxTime) given am maxTime when amPm is am', () => { | ||
const component = mount(<Hour12Input {...defaultProps} amPm="am" maxTime="5:35" />); | ||
const { container } = render(<Hour12Input {...defaultProps} amPm="am" maxTime="5:35" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('max')).toBe(5); | ||
expect(input).toHaveAttribute('max', '5'); | ||
}); | ||
it('has max = (hour in maxTime) given pm maxTime when amPm is pm', () => { | ||
const component = mount(<Hour12Input {...defaultProps} amPm="pm" maxTime="17:35" />); | ||
const { container } = render(<Hour12Input {...defaultProps} amPm="pm" maxTime="17:35" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('max')).toBe(5); | ||
expect(input).toHaveAttribute('max', '5'); | ||
}); | ||
it('has max = 12 given am maxTime when amPm is pm', () => { | ||
const component = mount(<Hour12Input {...defaultProps} amPm="pm" maxTime="5:35" />); | ||
it('has max = "12" given am maxTime when amPm is pm', () => { | ||
const { container } = render(<Hour12Input {...defaultProps} amPm="pm" maxTime="5:35" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('max')).toBe(12); | ||
expect(input).toHaveAttribute('max', '12'); | ||
}); | ||
it('has max = 12 given pm maxTime when amPm is am', () => { | ||
const component = mount(<Hour12Input {...defaultProps} amPm="am" maxTime="17:35" />); | ||
it('has max = "12" given pm maxTime when amPm is am', () => { | ||
const { container } = render(<Hour12Input {...defaultProps} amPm="am" maxTime="17:35" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('max')).toBe(12); | ||
expect(input).toHaveAttribute('max', '12'); | ||
}); | ||
it('has max = 12 given 12 pm minTime when amPm is pm', () => { | ||
const component = mount(<Hour12Input {...defaultProps} amPm="pm" maxTime="12:35" />); | ||
it('has max = "12" given 12 pm minTime when amPm is pm', () => { | ||
const { container } = render(<Hour12Input {...defaultProps} amPm="pm" maxTime="12:35" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('max')).toBe(12); | ||
expect(input).toHaveAttribute('max', '12'); | ||
}); | ||
}); |
import React from 'react'; | ||
import { mount } from 'enzyme'; | ||
import { render } from '@testing-library/react'; | ||
@@ -13,7 +13,7 @@ import Hour24Input from './Hour24Input'; | ||
it('renders an input', () => { | ||
const component = mount(<Hour24Input {...defaultProps} />); | ||
const { container } = render(<Hour24Input {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input).toHaveLength(1); | ||
expect(input).toBeInTheDocument(); | ||
}); | ||
@@ -24,7 +24,7 @@ | ||
const component = mount(<Hour24Input {...defaultProps} ariaLabel={hourAriaLabel} />); | ||
const { container } = render(<Hour24Input {...defaultProps} ariaLabel={hourAriaLabel} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('aria-label')).toBe(hourAriaLabel); | ||
expect(input).toHaveAttribute('aria-label', hourAriaLabel); | ||
}); | ||
@@ -35,66 +35,60 @@ | ||
const component = mount(<Hour24Input {...defaultProps} placeholder={hourPlaceholder} />); | ||
const { container } = render(<Hour24Input {...defaultProps} placeholder={hourPlaceholder} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('placeholder')).toBe(hourPlaceholder); | ||
expect(input).toHaveAttribute('placeholder', hourPlaceholder); | ||
}); | ||
it('renders "0" given showLeadingZeros if hour is <10', () => { | ||
const component = mount(<Hour24Input {...defaultProps} showLeadingZeros value="9" />); | ||
const { container } = render(<Hour24Input {...defaultProps} showLeadingZeros value="9" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(component.text()).toContain('0'); | ||
expect(input.prop('className')).toContain(`${defaultProps.className}__input--hasLeadingZero`); | ||
expect(container).toHaveTextContent('0'); | ||
expect(input).toHaveClass(`${defaultProps.className}__input--hasLeadingZero`); | ||
}); | ||
it('renders "0" given showLeadingZeros if hour is 0', () => { | ||
const component = mount(<Hour24Input {...defaultProps} showLeadingZeros value="0" />); | ||
const { container } = render(<Hour24Input {...defaultProps} showLeadingZeros value="0" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(component.text()).toContain('0'); | ||
expect(input.prop('className')).toContain(`${defaultProps.className}__input--hasLeadingZero`); | ||
expect(container).toHaveTextContent('0'); | ||
expect(input).toHaveClass(`${defaultProps.className}__input--hasLeadingZero`); | ||
}); | ||
it('does not render "0" given showLeadingZeros if hour is <10 with leading zero already', () => { | ||
const component = mount(<Hour24Input {...defaultProps} showLeadingZeros value="09" />); | ||
const { container } = render(<Hour24Input {...defaultProps} showLeadingZeros value="09" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(component.text()).not.toContain('0'); | ||
expect(input.prop('className')).not.toContain( | ||
`${defaultProps.className}__input--hasLeadingZero`, | ||
); | ||
expect(container).not.toHaveTextContent('0'); | ||
expect(input).not.toHaveClass(`${defaultProps.className}__input--hasLeadingZero`); | ||
}); | ||
it('does not render "0" given showLeadingZeros if hour is >=10', () => { | ||
const component = mount(<Hour24Input {...defaultProps} showLeadingZeros value="10" />); | ||
const { container } = render(<Hour24Input {...defaultProps} showLeadingZeros value="10" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(component.text()).not.toContain('0'); | ||
expect(input.prop('className')).not.toContain( | ||
`${defaultProps.className}__input--hasLeadingZero`, | ||
); | ||
expect(container).not.toHaveTextContent('0'); | ||
expect(input).not.toHaveClass(`${defaultProps.className}__input--hasLeadingZero`); | ||
}); | ||
it('does not render "0" if not given showLeadingZeros', () => { | ||
const component = mount(<Hour24Input {...defaultProps} value="9" />); | ||
const { container } = render(<Hour24Input {...defaultProps} value="9" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(component.text()).not.toContain('0'); | ||
expect(input.prop('className')).not.toContain( | ||
`${defaultProps.className}__input--hasLeadingZero`, | ||
); | ||
expect(container).not.toHaveTextContent('0'); | ||
expect(input).not.toHaveClass(`${defaultProps.className}__input--hasLeadingZero`); | ||
}); | ||
it('has proper name defined', () => { | ||
const component = mount(<Hour24Input {...defaultProps} />); | ||
const { container } = render(<Hour24Input {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('name')).toBe('hour24'); | ||
expect(input).toHaveAttribute('name', 'hour24'); | ||
}); | ||
@@ -105,8 +99,8 @@ | ||
const component = mount(<Hour24Input {...defaultProps} className={className} />); | ||
const { container } = render(<Hour24Input {...defaultProps} className={className} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.hasClass('react-time-picker__input')).toBe(true); | ||
expect(input.hasClass('react-time-picker__hour')).toBe(true); | ||
expect(input).toHaveClass('react-time-picker__input'); | ||
expect(input).toHaveClass('react-time-picker__hour'); | ||
}); | ||
@@ -117,39 +111,39 @@ | ||
const component = mount(<Hour24Input {...defaultProps} value={value} />); | ||
const { container } = render(<Hour24Input {...defaultProps} value={value} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('value')).toBe(value); | ||
expect(input).toHaveValue(Number(value)); | ||
}); | ||
it('does not disable input by default', () => { | ||
const component = mount(<Hour24Input {...defaultProps} />); | ||
const { container } = render(<Hour24Input {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('disabled')).toBeFalsy(); | ||
expect(input).not.toBeDisabled(); | ||
}); | ||
it('disables input given disabled flag', () => { | ||
const component = mount(<Hour24Input {...defaultProps} disabled />); | ||
const { container } = render(<Hour24Input {...defaultProps} disabled />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('disabled')).toBeTruthy(); | ||
expect(input).toBeDisabled(); | ||
}); | ||
it('is not required input by default', () => { | ||
const component = mount(<Hour24Input {...defaultProps} />); | ||
const { container } = render(<Hour24Input {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('required')).toBeFalsy(); | ||
expect(input).not.toBeRequired(); | ||
}); | ||
it('required input given required flag', () => { | ||
const component = mount(<Hour24Input {...defaultProps} required />); | ||
const { container } = render(<Hour24Input {...defaultProps} required />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('required')).toBeTruthy(); | ||
expect(input).toBeRequired(); | ||
}); | ||
@@ -160,3 +154,3 @@ | ||
mount(<Hour24Input {...defaultProps} inputRef={inputRef} />); | ||
render(<Hour24Input {...defaultProps} inputRef={inputRef} />); | ||
@@ -167,33 +161,33 @@ expect(inputRef).toHaveBeenCalled(); | ||
it('has min = 0 by default', () => { | ||
const component = mount(<Hour24Input {...defaultProps} />); | ||
it('has min = "0" by default', () => { | ||
const { container } = render(<Hour24Input {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('min')).toBe(0); | ||
expect(input).toHaveAttribute('min', '0'); | ||
}); | ||
it('has min = (hour in minTime) given minTime', () => { | ||
const component = mount(<Hour24Input {...defaultProps} minTime="17:35" />); | ||
const { container } = render(<Hour24Input {...defaultProps} minTime="17:35" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('min')).toBe(17); | ||
expect(input).toHaveAttribute('min', '17'); | ||
}); | ||
it('has max = 23 by default', () => { | ||
const component = mount(<Hour24Input {...defaultProps} />); | ||
it('has max = "23" by default', () => { | ||
const { container } = render(<Hour24Input {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('max')).toBe(23); | ||
expect(input).toHaveAttribute('max', '23'); | ||
}); | ||
it('has max = (hour in maxTime) given maxTime', () => { | ||
const component = mount(<Hour24Input {...defaultProps} maxTime="17:35" />); | ||
const { container } = render(<Hour24Input {...defaultProps} maxTime="17:35" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('max')).toBe(17); | ||
expect(input).toHaveAttribute('max', '17'); | ||
}); | ||
}); |
@@ -1,5 +0,4 @@ | ||
import React from 'react'; | ||
import React, { useLayoutEffect } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import mergeClassNames from 'merge-class-names'; | ||
import mergeRefs from 'merge-refs'; | ||
import updateInputWidth, { getFontShorthand } from 'update-input-width'; | ||
@@ -26,2 +25,14 @@ | ||
function updateInputWidthOnLoad(element) { | ||
if (document.readyState === 'complete') { | ||
return; | ||
} | ||
function onLoad() { | ||
updateInputWidth(element); | ||
} | ||
window.addEventListener('load', onLoad); | ||
} | ||
function updateInputWidthOnFontLoad(element) { | ||
@@ -109,2 +120,12 @@ if (!document.fonts) { | ||
}) { | ||
useLayoutEffect(() => { | ||
if (!inputRef || !inputRef.current) { | ||
return; | ||
} | ||
updateInputWidth(inputRef.current); | ||
updateInputWidthOnLoad(inputRef.current); | ||
updateInputWidthOnFontLoad(inputRef.current); | ||
}, [inputRef, value]); | ||
const hasLeadingZero = | ||
@@ -148,3 +169,3 @@ showLeadingZeros && value && value < 10 && (value === '0' || !value.toString().startsWith('0')); | ||
placeholder={placeholder} | ||
ref={mergeRefs(updateInputWidth, updateInputWidthOnFontLoad, inputRef)} | ||
ref={inputRef} | ||
required={required} | ||
@@ -151,0 +172,0 @@ step={step} |
import React from 'react'; | ||
import { mount } from 'enzyme'; | ||
import { render } from '@testing-library/react'; | ||
@@ -13,7 +13,7 @@ import MinuteInput from './MinuteInput'; | ||
it('renders an input', () => { | ||
const component = mount(<MinuteInput {...defaultProps} />); | ||
const { container } = render(<MinuteInput {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input).toHaveLength(1); | ||
expect(input).toBeInTheDocument(); | ||
}); | ||
@@ -24,7 +24,7 @@ | ||
const component = mount(<MinuteInput {...defaultProps} ariaLabel={minuteAriaLabel} />); | ||
const { container } = render(<MinuteInput {...defaultProps} ariaLabel={minuteAriaLabel} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('aria-label')).toBe(minuteAriaLabel); | ||
expect(input).toHaveAttribute('aria-label', minuteAriaLabel); | ||
}); | ||
@@ -35,55 +35,51 @@ | ||
const component = mount(<MinuteInput {...defaultProps} placeholder={minutePlaceholder} />); | ||
const { container } = render(<MinuteInput {...defaultProps} placeholder={minutePlaceholder} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('placeholder')).toBe(minutePlaceholder); | ||
expect(input).toHaveAttribute('placeholder', minutePlaceholder); | ||
}); | ||
it('renders "0" if minute is <10', () => { | ||
const component = mount(<MinuteInput {...defaultProps} value="9" />); | ||
const { container } = render(<MinuteInput {...defaultProps} value="9" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(component.text()).toContain('0'); | ||
expect(input.prop('className')).toContain(`${defaultProps.className}__input--hasLeadingZero`); | ||
expect(container).toHaveTextContent('0'); | ||
expect(input).toHaveClass(`${defaultProps.className}__input--hasLeadingZero`); | ||
}); | ||
it('renders "0" given showLeadingZeros if minute is 0', () => { | ||
const component = mount(<MinuteInput {...defaultProps} showLeadingZeros value="0" />); | ||
const { container } = render(<MinuteInput {...defaultProps} showLeadingZeros value="0" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(component.text()).toContain('0'); | ||
expect(input.prop('className')).toContain(`${defaultProps.className}__input--hasLeadingZero`); | ||
expect(container).toHaveTextContent('0'); | ||
expect(input).toHaveClass(`${defaultProps.className}__input--hasLeadingZero`); | ||
}); | ||
it('does not render "0" given showLeadingZeros if minute is <10 with leading zero already', () => { | ||
const component = mount(<MinuteInput {...defaultProps} showLeadingZeros value="09" />); | ||
const { container } = render(<MinuteInput {...defaultProps} showLeadingZeros value="09" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(component.text()).not.toContain('0'); | ||
expect(input.prop('className')).not.toContain( | ||
`${defaultProps.className}__input--hasLeadingZero`, | ||
); | ||
expect(container).not.toHaveTextContent('0'); | ||
expect(input).not.toHaveClass(`${defaultProps.className}__input--hasLeadingZero`); | ||
}); | ||
it('does not render "0" if minute is >=10', () => { | ||
const component = mount(<MinuteInput {...defaultProps} value="10" />); | ||
const { container } = render(<MinuteInput {...defaultProps} value="10" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(component.text()).not.toContain('0'); | ||
expect(input.prop('className')).not.toContain( | ||
`${defaultProps.className}__input--hasLeadingZero`, | ||
); | ||
expect(container).not.toHaveTextContent('0'); | ||
expect(input).not.toHaveClass(`${defaultProps.className}__input--hasLeadingZero`); | ||
}); | ||
it('has proper name defined', () => { | ||
const component = mount(<MinuteInput {...defaultProps} />); | ||
const { container } = render(<MinuteInput {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('name')).toBe('minute'); | ||
expect(input).toHaveAttribute('name', 'minute'); | ||
}); | ||
@@ -94,8 +90,8 @@ | ||
const component = mount(<MinuteInput {...defaultProps} className={className} />); | ||
const { container } = render(<MinuteInput {...defaultProps} className={className} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.hasClass('react-time-picker__input')).toBe(true); | ||
expect(input.hasClass('react-time-picker__minute')).toBe(true); | ||
expect(input).toHaveClass('react-time-picker__input'); | ||
expect(input).toHaveClass('react-time-picker__minute'); | ||
}); | ||
@@ -106,39 +102,39 @@ | ||
const component = mount(<MinuteInput {...defaultProps} value={value} />); | ||
const { container } = render(<MinuteInput {...defaultProps} value={value} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('value')).toBe(value); | ||
expect(input).toHaveValue(Number(value)); | ||
}); | ||
it('does not disable input by default', () => { | ||
const component = mount(<MinuteInput {...defaultProps} />); | ||
const { container } = render(<MinuteInput {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('disabled')).toBeFalsy(); | ||
expect(input).not.toBeDisabled(); | ||
}); | ||
it('disables input given disabled flag', () => { | ||
const component = mount(<MinuteInput {...defaultProps} disabled />); | ||
const { container } = render(<MinuteInput {...defaultProps} disabled />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('disabled')).toBeTruthy(); | ||
expect(input).toBeDisabled(); | ||
}); | ||
it('is not required input by default', () => { | ||
const component = mount(<MinuteInput {...defaultProps} />); | ||
const { container } = render(<MinuteInput {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('required')).toBeFalsy(); | ||
expect(input).not.toBeRequired(); | ||
}); | ||
it('required input given required flag', () => { | ||
const component = mount(<MinuteInput {...defaultProps} required />); | ||
const { container } = render(<MinuteInput {...defaultProps} required />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('required')).toBeTruthy(); | ||
expect(input).toBeRequired(); | ||
}); | ||
@@ -149,3 +145,3 @@ | ||
mount(<MinuteInput {...defaultProps} inputRef={inputRef} />); | ||
render(<MinuteInput {...defaultProps} inputRef={inputRef} />); | ||
@@ -156,49 +152,49 @@ expect(inputRef).toHaveBeenCalled(); | ||
it('has min = 0 by default', () => { | ||
const component = mount(<MinuteInput {...defaultProps} />); | ||
it('has min = "0" by default', () => { | ||
const { container } = render(<MinuteInput {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('min')).toBe(0); | ||
expect(input).toHaveAttribute('min', '0'); | ||
}); | ||
it('has min = 0 given minTime in a past hour', () => { | ||
const component = mount(<MinuteInput {...defaultProps} hour="22" minTime="21:40" />); | ||
it('has min = "0" given minTime in a past hour', () => { | ||
const { container } = render(<MinuteInput {...defaultProps} hour="22" minTime="21:40" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('min')).toBe(0); | ||
expect(input).toHaveAttribute('min', '0'); | ||
}); | ||
it('has min = (minute in minTime) given minTime in a current hour', () => { | ||
const component = mount(<MinuteInput {...defaultProps} hour="22" minTime="22:40" />); | ||
const { container } = render(<MinuteInput {...defaultProps} hour="22" minTime="22:40" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('min')).toBe(40); | ||
expect(input).toHaveAttribute('min', '40'); | ||
}); | ||
it('has max = 59 by default', () => { | ||
const component = mount(<MinuteInput {...defaultProps} />); | ||
it('has max = "59" by default', () => { | ||
const { container } = render(<MinuteInput {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('max')).toBe(59); | ||
expect(input).toHaveAttribute('max', '59'); | ||
}); | ||
it('has max = 59 given maxTime in a future hour', () => { | ||
const component = mount(<MinuteInput {...defaultProps} hour="22" maxTime="23:40" />); | ||
it('has max = "59" given maxTime in a future hour', () => { | ||
const { container } = render(<MinuteInput {...defaultProps} hour="22" maxTime="23:40" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('max')).toBe(59); | ||
expect(input).toHaveAttribute('max', '59'); | ||
}); | ||
it('has max = (minute in maxHour) given maxTime in a current hour', () => { | ||
const component = mount(<MinuteInput {...defaultProps} hour="22" maxTime="22:40" />); | ||
const { container } = render(<MinuteInput {...defaultProps} hour="22" maxTime="22:40" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('max')).toBe(40); | ||
expect(input).toHaveAttribute('max', '40'); | ||
}); | ||
}); |
import React from 'react'; | ||
import { shallow } from 'enzyme'; | ||
import { render } from '@testing-library/react'; | ||
@@ -13,17 +13,19 @@ import NativeInput from './NativeInput'; | ||
it('renders an input', () => { | ||
const component = shallow(<NativeInput {...defaultProps} />); | ||
const { container } = render(<NativeInput {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input).toHaveLength(1); | ||
expect(input).toBeInTheDocument(); | ||
}); | ||
it('applies given aria-label properly', () => { | ||
const nativeInputAriaLabel = 'Time'; | ||
const nativeInputAriaLabel = 'Date'; | ||
const component = shallow(<NativeInput {...defaultProps} ariaLabel={nativeInputAriaLabel} />); | ||
const { container } = render( | ||
<NativeInput {...defaultProps} ariaLabel={nativeInputAriaLabel} />, | ||
); | ||
const select = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(select.prop('aria-label')).toBe(nativeInputAriaLabel); | ||
expect(input).toHaveAttribute('aria-label', nativeInputAriaLabel); | ||
}); | ||
@@ -34,7 +36,7 @@ | ||
const component = shallow(<NativeInput {...defaultProps} name={name} />); | ||
const { container } = render(<NativeInput {...defaultProps} name={name} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('name')).toBe(name); | ||
expect(input).toHaveAttribute('name', name); | ||
}); | ||
@@ -50,50 +52,49 @@ | ||
const component = shallow( | ||
const { container } = render( | ||
<NativeInput {...defaultProps} value={value} valueType={valueType} />, | ||
); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('value').toString()).toBe(parsedValue); | ||
expect(input).toHaveValue(parsedValue); | ||
}); | ||
/* eslint-enable indent */ | ||
it('does not disable input by default', () => { | ||
const component = shallow(<NativeInput {...defaultProps} />); | ||
const { container } = render(<NativeInput {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('disabled')).toBeFalsy(); | ||
expect(input).not.toBeDisabled(); | ||
}); | ||
it('disables input given disabled flag', () => { | ||
const component = shallow(<NativeInput {...defaultProps} disabled />); | ||
const { container } = render(<NativeInput {...defaultProps} disabled />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('disabled')).toBeTruthy(); | ||
expect(input).toBeDisabled(); | ||
}); | ||
it('is not required input by default', () => { | ||
const component = shallow(<NativeInput {...defaultProps} />); | ||
const { container } = render(<NativeInput {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('required')).toBeFalsy(); | ||
expect(input).not.toBeRequired(); | ||
}); | ||
it('required input given required flag', () => { | ||
const component = shallow(<NativeInput {...defaultProps} required />); | ||
const { container } = render(<NativeInput {...defaultProps} required />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('required')).toBeTruthy(); | ||
expect(input).toBeRequired(); | ||
}); | ||
it('has no min by default', () => { | ||
const component = shallow(<NativeInput {...defaultProps} />); | ||
const { container } = render(<NativeInput {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('min')).toBeFalsy(); | ||
expect(input).not.toHaveAttribute('min'); | ||
}); | ||
@@ -109,9 +110,9 @@ | ||
({ valueType, parsedMin }) => { | ||
const component = shallow( | ||
const { container } = render( | ||
<NativeInput {...defaultProps} minTime="22:00:00" valueType={valueType} />, | ||
); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('min').toString()).toBe(parsedMin); | ||
expect(input).toHaveAttribute('min', parsedMin); | ||
}, | ||
@@ -128,9 +129,9 @@ ); | ||
({ valueType, parsedMin }) => { | ||
const component = shallow( | ||
const { container } = render( | ||
<NativeInput {...defaultProps} minTime="22:17:41" valueType={valueType} />, | ||
); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('min').toString()).toBe(parsedMin); | ||
expect(input).toHaveAttribute('min', parsedMin); | ||
}, | ||
@@ -140,7 +141,7 @@ ); | ||
it('has no max by default', () => { | ||
const component = shallow(<NativeInput {...defaultProps} />); | ||
const { container } = render(<NativeInput {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('max')).toBeFalsy(); | ||
expect(input).not.toHaveAttribute('max'); | ||
}); | ||
@@ -156,9 +157,9 @@ | ||
({ valueType, parsedMax }) => { | ||
const component = shallow( | ||
const { container } = render( | ||
<NativeInput {...defaultProps} maxTime="22:00:00" valueType={valueType} />, | ||
); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('max').toString()).toBe(parsedMax); | ||
expect(input).toHaveAttribute('max', parsedMax); | ||
}, | ||
@@ -175,11 +176,11 @@ ); | ||
({ valueType, parsedMax }) => { | ||
const component = shallow( | ||
const { container } = render( | ||
<NativeInput {...defaultProps} maxTime="22:17:41" valueType={valueType} />, | ||
); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('max').toString()).toBe(parsedMax); | ||
expect(input).toHaveAttribute('max', parsedMax); | ||
}, | ||
); | ||
}); |
import React from 'react'; | ||
import { mount } from 'enzyme'; | ||
import { render } from '@testing-library/react'; | ||
@@ -13,7 +13,7 @@ import SecondInput from './SecondInput'; | ||
it('renders an input', () => { | ||
const component = mount(<SecondInput {...defaultProps} />); | ||
const { container } = render(<SecondInput {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input).toHaveLength(1); | ||
expect(input).toBeInTheDocument(); | ||
}); | ||
@@ -24,7 +24,7 @@ | ||
const component = mount(<SecondInput {...defaultProps} ariaLabel={secondAriaLabel} />); | ||
const { container } = render(<SecondInput {...defaultProps} ariaLabel={secondAriaLabel} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('aria-label')).toBe(secondAriaLabel); | ||
expect(input).toHaveAttribute('aria-label', secondAriaLabel); | ||
}); | ||
@@ -35,55 +35,51 @@ | ||
const component = mount(<SecondInput {...defaultProps} placeholder={secondPlaceholder} />); | ||
const { container } = render(<SecondInput {...defaultProps} placeholder={secondPlaceholder} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('placeholder')).toBe(secondPlaceholder); | ||
expect(input).toHaveAttribute('placeholder', secondPlaceholder); | ||
}); | ||
it('renders "0" if second is <10', () => { | ||
const component = mount(<SecondInput {...defaultProps} value="9" />); | ||
const { container } = render(<SecondInput {...defaultProps} value="9" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(component.text()).toContain('0'); | ||
expect(input.prop('className')).toContain(`${defaultProps.className}__input--hasLeadingZero`); | ||
expect(container).toHaveTextContent('0'); | ||
expect(input).toHaveClass(`${defaultProps.className}__input--hasLeadingZero`); | ||
}); | ||
it('renders "0" given showLeadingZeros if second is 0', () => { | ||
const component = mount(<SecondInput {...defaultProps} showLeadingZeros value="0" />); | ||
const { container } = render(<SecondInput {...defaultProps} showLeadingZeros value="0" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(component.text()).toContain('0'); | ||
expect(input.prop('className')).toContain(`${defaultProps.className}__input--hasLeadingZero`); | ||
expect(container).toHaveTextContent('0'); | ||
expect(input).toHaveClass(`${defaultProps.className}__input--hasLeadingZero`); | ||
}); | ||
it('does not render "0" given showLeadingZeros if second is <10 with leading zero already', () => { | ||
const component = mount(<SecondInput {...defaultProps} showLeadingZeros value="09" />); | ||
const { container } = render(<SecondInput {...defaultProps} showLeadingZeros value="09" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(component.text()).not.toContain('0'); | ||
expect(input.prop('className')).not.toContain( | ||
`${defaultProps.className}__input--hasLeadingZero`, | ||
); | ||
expect(container).not.toHaveTextContent('0'); | ||
expect(input).not.toHaveClass(`${defaultProps.className}__input--hasLeadingZero`); | ||
}); | ||
it('does not render "0" if second is >=10', () => { | ||
const component = mount(<SecondInput {...defaultProps} value="10" />); | ||
const { container } = render(<SecondInput {...defaultProps} value="10" />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(component.text()).not.toContain('0'); | ||
expect(input.prop('className')).not.toContain( | ||
`${defaultProps.className}__input--hasLeadingZero`, | ||
); | ||
expect(container).not.toHaveTextContent('0'); | ||
expect(input).not.toHaveClass(`${defaultProps.className}__input--hasLeadingZero`); | ||
}); | ||
it('has proper name defined', () => { | ||
const component = mount(<SecondInput {...defaultProps} />); | ||
const { container } = render(<SecondInput {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('name')).toBe('second'); | ||
expect(input).toHaveAttribute('name', 'second'); | ||
}); | ||
@@ -94,8 +90,8 @@ | ||
const component = mount(<SecondInput {...defaultProps} className={className} />); | ||
const { container } = render(<SecondInput {...defaultProps} className={className} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.hasClass('react-time-picker__input')).toBe(true); | ||
expect(input.hasClass('react-time-picker__second')).toBe(true); | ||
expect(input).toHaveClass('react-time-picker__input'); | ||
expect(input).toHaveClass('react-time-picker__second'); | ||
}); | ||
@@ -106,39 +102,39 @@ | ||
const component = mount(<SecondInput {...defaultProps} value={value} />); | ||
const { container } = render(<SecondInput {...defaultProps} value={value} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('value')).toBe(value); | ||
expect(input).toHaveValue(Number(value)); | ||
}); | ||
it('does not disable input by default', () => { | ||
const component = mount(<SecondInput {...defaultProps} />); | ||
const { container } = render(<SecondInput {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('disabled')).toBeFalsy(); | ||
expect(input).not.toBeDisabled(); | ||
}); | ||
it('disables input given disabled flag', () => { | ||
const component = mount(<SecondInput {...defaultProps} disabled />); | ||
const { container } = render(<SecondInput {...defaultProps} disabled />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('disabled')).toBeTruthy(); | ||
expect(input).toBeDisabled(); | ||
}); | ||
it('is not required input by default', () => { | ||
const component = mount(<SecondInput {...defaultProps} />); | ||
const { container } = render(<SecondInput {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('required')).toBeFalsy(); | ||
expect(input).not.toBeRequired(); | ||
}); | ||
it('required input given required flag', () => { | ||
const component = mount(<SecondInput {...defaultProps} required />); | ||
const { container } = render(<SecondInput {...defaultProps} required />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('required')).toBeTruthy(); | ||
expect(input).toBeRequired(); | ||
}); | ||
@@ -149,3 +145,3 @@ | ||
mount(<SecondInput {...defaultProps} inputRef={inputRef} />); | ||
render(<SecondInput {...defaultProps} inputRef={inputRef} />); | ||
@@ -156,57 +152,57 @@ expect(inputRef).toHaveBeenCalled(); | ||
it('has min = 0 by default', () => { | ||
const component = mount(<SecondInput {...defaultProps} />); | ||
it('has min = "0" by default', () => { | ||
const { container } = render(<SecondInput {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('min')).toBe(0); | ||
expect(input).toHaveAttribute('min', '0'); | ||
}); | ||
it('has min = 0 given minDate in a past minute', () => { | ||
const component = mount( | ||
it('has min = "0" given minDate in a past minute', () => { | ||
const { container } = render( | ||
<SecondInput {...defaultProps} hour="22" minTime="21:40:15" minute="40" />, | ||
); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('min')).toBe(0); | ||
expect(input).toHaveAttribute('min', '0'); | ||
}); | ||
it('has min = (second in minTime) given minTime in a current minute', () => { | ||
const component = mount( | ||
const { container } = render( | ||
<SecondInput {...defaultProps} hour="22" minTime="22:40:15" minute="40" />, | ||
); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('min')).toBe(15); | ||
expect(input).toHaveAttribute('min', '15'); | ||
}); | ||
it('has max = 59 by default', () => { | ||
const component = mount(<SecondInput {...defaultProps} />); | ||
it('has max = "59" by default', () => { | ||
const { container } = render(<SecondInput {...defaultProps} />); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('max')).toBe(59); | ||
expect(input).toHaveAttribute('max', '59'); | ||
}); | ||
it('has max = 59 given maxTime in a future minute', () => { | ||
const component = mount( | ||
it('has max = "59" given maxTime in a future minute', () => { | ||
const { container } = render( | ||
<SecondInput {...defaultProps} hour="22" maxTime="23:40:15" minute="40" />, | ||
); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('max')).toBe(59); | ||
expect(input).toHaveAttribute('max', '59'); | ||
}); | ||
it('has max = (second in maxHour) given maxTime in a current minute', () => { | ||
const component = mount( | ||
const { container } = render( | ||
<SecondInput {...defaultProps} hour="22" maxTime="22:40:15" minute="40" />, | ||
); | ||
const input = component.find('input'); | ||
const input = container.querySelector('input'); | ||
expect(input.prop('max')).toBe(15); | ||
expect(input).toHaveAttribute('max', '15'); | ||
}); | ||
}); |
@@ -1,2 +0,3 @@ | ||
import React, { PureComponent } from 'react'; | ||
import React, { createRef, PureComponent } from 'react'; | ||
import { createPortal } from 'react-dom'; | ||
import PropTypes from 'prop-types'; | ||
@@ -31,2 +32,6 @@ import makeEventProps from 'make-event-props'; | ||
wrapper = createRef(); | ||
clockWrapper = createRef(); | ||
componentDidMount() { | ||
@@ -56,5 +61,12 @@ this.handleOutsideActionListeners(); | ||
onOutsideAction = (event) => { | ||
const { wrapper, clockWrapper } = this; | ||
// Try event.composedPath first to handle clicks inside a Shadow DOM. | ||
const target = 'composedPath' in event ? event.composedPath()[0] : event.target; | ||
if (this.wrapper && !this.wrapper.contains(target)) { | ||
if ( | ||
wrapper.current && | ||
!wrapper.current.contains(target) && | ||
(!clockWrapper.current || !clockWrapper.current.contains(target)) | ||
) { | ||
this.closeClock(); | ||
@@ -89,3 +101,3 @@ } | ||
if (openClockOnFocus) { | ||
if (event.target.getAttribute('data-select') === 'true') { | ||
if (event.target.dataset.select === 'true') { | ||
return; | ||
@@ -242,2 +254,3 @@ } | ||
onChange, | ||
portalContainer, | ||
value, | ||
@@ -248,2 +261,4 @@ ...clockProps | ||
const className = `${baseClassName}__clock`; | ||
const classNames = mergeClassNames(className, `${className}--${isOpen ? 'open' : 'closed'}`); | ||
const [valueFrom] = [].concat(value); | ||
@@ -253,3 +268,20 @@ | ||
return ( | ||
const clock = ( | ||
<Clock | ||
className={clockClassName} | ||
renderMinuteHand={maxDetailIndex > 0} | ||
renderSecondHand={maxDetailIndex > 1} | ||
value={valueFrom} | ||
{...clockProps} | ||
/> | ||
); | ||
return portalContainer ? ( | ||
createPortal( | ||
<div ref={this.clockWrapper} className={classNames}> | ||
{clock} | ||
</div>, | ||
portalContainer, | ||
) | ||
) : ( | ||
<Fit> | ||
@@ -262,11 +294,5 @@ <div | ||
}} | ||
className={mergeClassNames(className, `${className}--${isOpen ? 'open' : 'closed'}`)} | ||
className={classNames} | ||
> | ||
<Clock | ||
className={clockClassName} | ||
renderMinuteHand={maxDetailIndex > 0} | ||
renderSecondHand={maxDetailIndex > 1} | ||
value={valueFrom} | ||
{...clockProps} | ||
/> | ||
{clock} | ||
</div> | ||
@@ -294,9 +320,3 @@ </Fit> | ||
onFocus={this.onFocus} | ||
ref={(ref) => { | ||
if (!ref) { | ||
return; | ||
} | ||
this.wrapper = ref; | ||
}} | ||
ref={this.wrapper} | ||
> | ||
@@ -380,2 +400,3 @@ {this.renderInputs()} | ||
openClockOnFocus: PropTypes.bool, | ||
portalContainer: PropTypes.object, | ||
required: PropTypes.bool, | ||
@@ -382,0 +403,0 @@ secondAriaLabel: PropTypes.string, |
@@ -1,3 +0,3 @@ | ||
import React from 'react'; | ||
import { mount } from 'enzyme'; | ||
import React, { createRef } from 'react'; | ||
import { fireEvent, render, waitForElementToBeRemoved } from '@testing-library/react'; | ||
@@ -8,7 +8,7 @@ import TimePicker from './TimePicker'; | ||
it('passes default name to TimeInput', () => { | ||
const component = mount(<TimePicker />); | ||
const { container } = render(<TimePicker />); | ||
const timeInput = component.find('TimeInput'); | ||
const nativeInput = container.querySelector('input[type="time"]'); | ||
expect(timeInput.prop('name')).toBe('time'); | ||
expect(nativeInput).toHaveAttribute('name', 'time'); | ||
}); | ||
@@ -19,34 +19,34 @@ | ||
const component = mount(<TimePicker name={name} />); | ||
const { container } = render(<TimePicker name={name} />); | ||
const timeInput = component.find('TimeInput'); | ||
const nativeInput = container.querySelector('input[type="time"]'); | ||
expect(timeInput.prop('name')).toBe(name); | ||
expect(nativeInput).toHaveAttribute('name', name); | ||
}); | ||
it('passes autoFocus flag to TimeInput', () => { | ||
// See https://github.com/jsdom/jsdom/issues/3041 | ||
it.skip('passes autoFocus flag to TimeInput', () => { | ||
// eslint-disable-next-line jsx-a11y/no-autofocus | ||
const component = mount(<TimePicker autoFocus />); | ||
const { container } = render(<TimePicker autoFocus />); | ||
const timeInput = component.find('TimeInput'); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
expect(timeInput.prop('autoFocus')).toBeTruthy(); | ||
expect(customInputs[0]).toHaveAttribute('autofocus'); | ||
}); | ||
it('passes disabled flag to TimeInput', () => { | ||
const component = mount(<TimePicker disabled />); | ||
const { container } = render(<TimePicker disabled />); | ||
const timeInput = component.find('TimeInput'); | ||
const nativeInput = container.querySelector('input[type="time"]'); | ||
expect(timeInput.prop('disabled')).toBeTruthy(); | ||
expect(nativeInput).toBeDisabled(); | ||
}); | ||
it('passes format to TimeInput', () => { | ||
const format = 'H:mm:ss'; | ||
const { container } = render(<TimePicker format="ss" />); | ||
const component = mount(<TimePicker format={format} />); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
const timeInput = component.find('TimeInput'); | ||
expect(timeInput.prop('format')).toBe(format); | ||
expect(customInputs).toHaveLength(1); | ||
expect(customInputs[0]).toHaveAttribute('name', 'second'); | ||
}); | ||
@@ -65,15 +65,23 @@ | ||
const component = mount(<TimePicker {...ariaLabelProps} />); | ||
const { container } = render(<TimePicker {...ariaLabelProps} maxDetail="second" />); | ||
const clockButton = component.find('button.react-time-picker__clock-button'); | ||
const clearButton = component.find('button.react-time-picker__clear-button'); | ||
const timeInput = component.find('TimeInput'); | ||
const clockButton = container.querySelector('button.react-time-picker__clock-button'); | ||
const clearButton = container.querySelector('button.react-time-picker__clear-button'); | ||
expect(clockButton.prop('aria-label')).toBe(ariaLabelProps.clockAriaLabel); | ||
expect(clearButton.prop('aria-label')).toBe(ariaLabelProps.clearAriaLabel); | ||
expect(timeInput.prop('amPmAriaLabel')).toBe(ariaLabelProps.amPmAriaLabel); | ||
expect(timeInput.prop('hourAriaLabel')).toBe(ariaLabelProps.hourAriaLabel); | ||
expect(timeInput.prop('minuteAriaLabel')).toBe(ariaLabelProps.minuteAriaLabel); | ||
expect(timeInput.prop('nativeInputAriaLabel')).toBe(ariaLabelProps.nativeInputAriaLabel); | ||
expect(timeInput.prop('secondAriaLabel')).toBe(ariaLabelProps.secondAriaLabel); | ||
const nativeInput = container.querySelector('input[type="time"]'); | ||
const amPmSelect = container.querySelector('select[name="amPm"]'); | ||
const hourInput = container.querySelector('input[name="hour12"]'); | ||
const minuteInput = container.querySelector('input[name="minute"]'); | ||
const secondInput = container.querySelector('input[name="second"]'); | ||
expect(clockButton).toHaveAttribute('aria-label', ariaLabelProps.clockAriaLabel); | ||
expect(clearButton).toHaveAttribute('aria-label', ariaLabelProps.clearAriaLabel); | ||
expect(nativeInput).toHaveAttribute('aria-label', ariaLabelProps.nativeInputAriaLabel); | ||
expect(amPmSelect).toHaveAttribute('aria-label', ariaLabelProps.amPmAriaLabel); | ||
expect(hourInput).toHaveAttribute('aria-label', ariaLabelProps.hourAriaLabel); | ||
expect(minuteInput).toHaveAttribute('aria-label', ariaLabelProps.minuteAriaLabel); | ||
expect(secondInput).toHaveAttribute('aria-label', ariaLabelProps.secondAriaLabel); | ||
}); | ||
@@ -88,9 +96,11 @@ | ||
const component = mount(<TimePicker {...placeholderProps} />); | ||
const { container } = render(<TimePicker {...placeholderProps} maxDetail="second" />); | ||
const timeInput = component.find('TimeInput'); | ||
const hourInput = container.querySelector('input[name="hour12"]'); | ||
const minuteInput = container.querySelector('input[name="minute"]'); | ||
const secondInput = container.querySelector('input[name="second"]'); | ||
expect(timeInput.prop('hourPlaceholder')).toBe(placeholderProps.hourPlaceholder); | ||
expect(timeInput.prop('minutePlaceholder')).toBe(placeholderProps.minutePlaceholder); | ||
expect(timeInput.prop('secondPlaceholder')).toBe(placeholderProps.secondPlaceholder); | ||
expect(hourInput).toHaveAttribute('placeholder', placeholderProps.hourPlaceholder); | ||
expect(minuteInput).toHaveAttribute('placeholder', placeholderProps.minutePlaceholder); | ||
expect(secondInput).toHaveAttribute('placeholder', placeholderProps.secondPlaceholder); | ||
}); | ||
@@ -102,7 +112,7 @@ | ||
const component = mount(<TimePicker value={value} />); | ||
const { container } = render(<TimePicker value={value} />); | ||
const timeInput = component.find('TimeInput'); | ||
const nativeInput = container.querySelector('input[type="time"]'); | ||
expect(timeInput.prop('value')).toBe(value); | ||
expect(nativeInput).toHaveValue('00:00'); | ||
}); | ||
@@ -114,7 +124,7 @@ | ||
const component = mount(<TimePicker value={[value1, value2]} />); | ||
const { container } = render(<TimePicker value={[value1, value2]} />); | ||
const timeInput = component.find('TimeInput'); | ||
const nativeInput = container.querySelector('input[type="time"]'); | ||
expect(timeInput.prop('value')).toBe(value1); | ||
expect(nativeInput).toHaveValue('00:00'); | ||
}); | ||
@@ -126,7 +136,7 @@ }); | ||
const component = mount(<TimePicker className={className} />); | ||
const { container } = render(<TimePicker className={className} />); | ||
const wrapperClassName = component.prop('className'); | ||
const wrapper = container.firstChild; | ||
expect(wrapperClassName.includes(className)).toBe(true); | ||
expect(wrapper).toHaveClass(className); | ||
}); | ||
@@ -137,83 +147,76 @@ | ||
const component = mount(<TimePicker clockClassName={clockClassName} isOpen />); | ||
const { container } = render(<TimePicker clockClassName={clockClassName} isOpen />); | ||
const clock = component.find('Clock'); | ||
const clockWrapperClassName = clock.prop('className'); | ||
const clock = container.querySelector('.react-clock'); | ||
expect(clockWrapperClassName.includes(clockClassName)).toBe(true); | ||
expect(clock).toHaveClass(clockClassName); | ||
}); | ||
it('renders TimeInput component', () => { | ||
const component = mount(<TimePicker />); | ||
const { container } = render(<TimePicker />); | ||
const timeInput = component.find('TimeInput'); | ||
const nativeInput = container.querySelector('input[type="time"]'); | ||
expect(timeInput).toHaveLength(1); | ||
expect(nativeInput).toBeInTheDocument(); | ||
}); | ||
it('renders clear button', () => { | ||
const component = mount(<TimePicker />); | ||
const { container } = render(<TimePicker />); | ||
const clearButton = component.find('button.react-time-picker__clear-button'); | ||
const clearButton = container.querySelector('button.react-time-picker__clear-button'); | ||
expect(clearButton).toHaveLength(1); | ||
expect(clearButton).toBeInTheDocument(); | ||
}); | ||
it('renders clock button', () => { | ||
const component = mount(<TimePicker />); | ||
const { container } = render(<TimePicker />); | ||
const clockButton = component.find('button.react-time-picker__clock-button'); | ||
const clockButton = container.querySelector('button.react-time-picker__clock-button'); | ||
expect(clockButton).toHaveLength(1); | ||
expect(clockButton).toBeInTheDocument(); | ||
}); | ||
it('renders TimeInput and Clock component when given isOpen flag', () => { | ||
const component = mount(<TimePicker isOpen />); | ||
it('renders Clock component when given isOpen flag', () => { | ||
const { container } = render(<TimePicker isOpen />); | ||
const timeInput = component.find('TimeInput'); | ||
const clock = component.find('Clock'); | ||
const clock = container.querySelector('.react-clock'); | ||
expect(timeInput).toHaveLength(1); | ||
expect(clock).toHaveLength(1); | ||
expect(clock).toBeInTheDocument(); | ||
}); | ||
it('does not render Clock component when given disableClock & isOpen flags', () => { | ||
const component = mount(<TimePicker disableClock isOpen />); | ||
const { container } = render(<TimePicker disableClock isOpen />); | ||
const timeInput = component.find('TimeInput'); | ||
const clock = component.find('Clock'); | ||
const clock = container.querySelector('.react-clock'); | ||
expect(timeInput).toHaveLength(1); | ||
expect(clock).toHaveLength(0); | ||
expect(clock).toBeFalsy(); | ||
}); | ||
it('opens Clock component when given isOpen flag by changing props', () => { | ||
const component = mount(<TimePicker />); | ||
const { container, rerender } = render(<TimePicker />); | ||
const clock = component.find('Clock'); | ||
const clock = container.querySelector('.react-clock'); | ||
expect(clock).toHaveLength(0); | ||
expect(clock).toBeFalsy(); | ||
component.setProps({ isOpen: true }); | ||
component.update(); | ||
rerender(<TimePicker isOpen />); | ||
const clock2 = component.find('Clock'); | ||
const clock2 = container.querySelector('.react-clock'); | ||
expect(clock2).toHaveLength(1); | ||
expect(clock2).toBeInTheDocument(); | ||
}); | ||
it('opens Clock component when clicking on a button', () => { | ||
const component = mount(<TimePicker />); | ||
const { container } = render(<TimePicker />); | ||
const clock = component.find('Clock'); | ||
const button = component.find('button.react-time-picker__clock-button'); | ||
const clock = container.querySelector('.react-clock'); | ||
const button = container.querySelector('button.react-time-picker__clock-button'); | ||
expect(clock).toHaveLength(0); | ||
expect(clock).toBeFalsy(); | ||
button.simulate('click'); | ||
component.update(); | ||
fireEvent.click(button); | ||
const clock2 = component.find('Clock'); | ||
const clock2 = container.querySelector('.react-clock'); | ||
expect(clock2).toHaveLength(1); | ||
expect(clock2).toBeInTheDocument(); | ||
}); | ||
@@ -223,63 +226,59 @@ | ||
it('opens Clock component when focusing on an input inside by default', () => { | ||
const component = mount(<TimePicker />); | ||
const { container } = render(<TimePicker />); | ||
const clock = component.find('Clock'); | ||
const input = component.find('input[name^="hour"]'); | ||
const clock = container.querySelector('.react-clock'); | ||
const input = container.querySelector('input[name^="hour"]'); | ||
expect(clock).toHaveLength(0); | ||
expect(clock).toBeFalsy(); | ||
input.simulate('focus'); | ||
component.update(); | ||
fireEvent.focus(input); | ||
const clock2 = component.find('Clock'); | ||
const clock2 = container.querySelector('.react-clock'); | ||
expect(clock2).toHaveLength(1); | ||
expect(clock2).toBeInTheDocument(); | ||
}); | ||
it('opens Clock component when focusing on an input inside given openClockOnFocus = true', () => { | ||
const component = mount(<TimePicker openClockOnFocus />); | ||
const { container } = render(<TimePicker openClockOnFocus />); | ||
const clock = component.find('Clock'); | ||
const input = component.find('input[name^="hour"]'); | ||
const clock = container.querySelector('.react-clock'); | ||
const input = container.querySelector('input[name^="hour"]'); | ||
expect(clock).toHaveLength(0); | ||
expect(clock).toBeFalsy(); | ||
input.simulate('focus'); | ||
component.update(); | ||
fireEvent.focus(input); | ||
const clock2 = component.find('Clock'); | ||
const clock2 = container.querySelector('.react-clock'); | ||
expect(clock2).toHaveLength(1); | ||
expect(clock2).toBeInTheDocument(); | ||
}); | ||
it('does not open Clock component when focusing on an input inside given openClockOnFocus = false', () => { | ||
const component = mount(<TimePicker openClockOnFocus={false} />); | ||
const { container } = render(<TimePicker openClockOnFocus={false} />); | ||
const clock = component.find('Clock'); | ||
const input = component.find('input[name^="hour"]'); | ||
const clock = container.querySelector('.react-clock'); | ||
const input = container.querySelector('input[name^="hour"]'); | ||
expect(clock).toHaveLength(0); | ||
expect(clock).toBeFalsy(); | ||
input.simulate('focus'); | ||
component.update(); | ||
fireEvent.focus(input); | ||
const clock2 = component.find('Clock'); | ||
const clock2 = container.querySelector('.react-clock'); | ||
expect(clock2).toHaveLength(0); | ||
expect(clock2).toBeFalsy(); | ||
}); | ||
it('does not open Clock component when focusing on a select element', () => { | ||
const component = mount(<TimePicker format="hh:mm:ss a" />); | ||
const { container } = render(<TimePicker format="hh:mm:ss a" />); | ||
const clock = component.find('Clock'); | ||
const select = component.find('select[name="amPm"]'); | ||
const clock = container.querySelector('.react-clock'); | ||
const select = container.querySelector('select[name="amPm"]'); | ||
expect(clock).toHaveLength(0); | ||
expect(clock).toBeFalsy(); | ||
select.simulate('focus'); | ||
component.update(); | ||
fireEvent.focus(select); | ||
const clock2 = component.find('Clock'); | ||
const clock2 = container.querySelector('.react-clock'); | ||
expect(clock2).toHaveLength(0); | ||
expect(clock2).toBeFalsy(); | ||
}); | ||
@@ -292,10 +291,7 @@ }); | ||
const component = mount(<TimePicker isOpen />, { attachTo: root }); | ||
const { container } = render(<TimePicker isOpen />, { attachTo: root }); | ||
const event = document.createEvent('MouseEvent'); | ||
event.initEvent('mousedown', true, true); | ||
document.body.dispatchEvent(event); | ||
component.update(); | ||
fireEvent.mouseDown(document.body); | ||
expect(component.state('isOpen')).toBe(false); | ||
waitForElementToBeRemoved(() => container.querySelector('.react-clock')); | ||
}); | ||
@@ -307,10 +303,7 @@ | ||
const component = mount(<TimePicker isOpen />, { attachTo: root }); | ||
const { container } = render(<TimePicker isOpen />, { attachTo: root }); | ||
const event = document.createEvent('FocusEvent'); | ||
event.initEvent('focusin', true, true); | ||
document.body.dispatchEvent(event); | ||
component.update(); | ||
fireEvent.focusIn(document.body); | ||
expect(component.state('isOpen')).toBe(false); | ||
waitForElementToBeRemoved(() => container.querySelector('.react-clock')); | ||
}); | ||
@@ -322,63 +315,72 @@ | ||
const component = mount(<TimePicker isOpen />, { attachTo: root }); | ||
const { container } = render(<TimePicker isOpen />, { attachTo: root }); | ||
const event = document.createEvent('TouchEvent'); | ||
event.initEvent('touchstart', true, true); | ||
document.body.dispatchEvent(event); | ||
component.update(); | ||
fireEvent.touchStart(document.body); | ||
expect(component.state('isOpen')).toBe(false); | ||
waitForElementToBeRemoved(() => container.querySelector('.react-clock')); | ||
}); | ||
it('does not close Clock component when focused inside', () => { | ||
const component = mount(<TimePicker isOpen />); | ||
const { container } = render(<TimePicker isOpen />); | ||
const customInputs = component.find('input[data-input]'); | ||
const hourInput = customInputs.at(0); | ||
const minuteInput = customInputs.at(1); | ||
const customInputs = container.querySelectorAll('input[data-input]'); | ||
const hourInput = customInputs[0]; | ||
const minuteInput = customInputs[1]; | ||
hourInput.simulate('blur'); | ||
minuteInput.simulate('focus'); | ||
component.update(); | ||
fireEvent.blur(hourInput); | ||
fireEvent.focus(minuteInput); | ||
expect(component.state('isOpen')).toBe(true); | ||
const clock = container.querySelector('.react-clock'); | ||
expect(clock).toBeInTheDocument(); | ||
}); | ||
it('closes Clock when calling internal onChange by default', () => { | ||
const component = mount(<TimePicker isOpen />); | ||
const instance = createRef(); | ||
const { onChange } = component.instance(); | ||
const { container } = render(<TimePicker isOpen ref={instance} />); | ||
const { onChange } = instance.current; | ||
onChange(new Date()); | ||
expect(component.state('isOpen')).toBe(false); | ||
waitForElementToBeRemoved(() => container.querySelector('.react-clock')); | ||
}); | ||
it('does not close Clock when calling internal onChange with prop closeClock = false', () => { | ||
const component = mount(<TimePicker closeClock={false} isOpen />); | ||
const instance = createRef(); | ||
const { onChange } = component.instance(); | ||
const { container } = render(<TimePicker closeClock={false} isOpen ref={instance} />); | ||
const { onChange } = instance.current; | ||
onChange(new Date()); | ||
expect(component.state('isOpen')).toBe(true); | ||
const clock = container.querySelector('.react-clock'); | ||
expect(clock).toBeInTheDocument(); | ||
}); | ||
it('does not close Clock when calling internal onChange with closeClock = false', () => { | ||
const component = mount(<TimePicker isOpen />); | ||
const instance = createRef(); | ||
const { onChange } = component.instance(); | ||
const { container } = render(<TimePicker isOpen ref={instance} />); | ||
const { onChange } = instance.current; | ||
onChange(new Date(), false); | ||
expect(component.state('isOpen')).toBe(true); | ||
const clock = container.querySelector('.react-clock'); | ||
expect(clock).toBeInTheDocument(); | ||
}); | ||
it('calls onChange callback when calling internal onChange', () => { | ||
const instance = createRef(); | ||
const nextValue = '22:41:28'; | ||
const onChange = jest.fn(); | ||
const component = mount(<TimePicker onChange={onChange} />); | ||
render(<TimePicker onChange={onChange} ref={instance} />); | ||
const { onChange: onChangeInternal } = component.instance(); | ||
const { onChange: onChangeInternal } = instance.current; | ||
@@ -393,11 +395,10 @@ onChangeInternal(nextValue); | ||
const component = mount(<TimePicker onChange={onChange} />); | ||
const { container } = render(<TimePicker onChange={onChange} />); | ||
const clock = component.find('Clock'); | ||
const button = component.find('button.react-time-picker__clear-button'); | ||
const clock = container.querySelector('.react-clock'); | ||
const button = container.querySelector('button.react-time-picker__clear-button'); | ||
expect(clock).toHaveLength(0); | ||
expect(clock).toBeFalsy(); | ||
button.simulate('click'); | ||
component.update(); | ||
fireEvent.click(button); | ||
@@ -404,0 +405,0 @@ expect(onChange).toHaveBeenCalledWith(null); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
225303
10
4760
139
17
- Removedmerge-refs@^1.0.0
- Removedmerge-refs@1.3.0(transitive)
Updatedreact-clock@^3.1.0