@wix/design-system
Version:
@wix/design-system
605 lines (603 loc) • 25.1 kB
JavaScript
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
var _jsxFileName = "/home/builduser/work/57e038ea7326c1ec/packages/wix-design-system/dist/esm/TimeInput/test/TimeInput.mask.spec.jsx",
_this = this;
import _regeneratorRuntime from "@babel/runtime/regenerator";
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
import React from 'react';
import { withMask } from 'use-mask-input';
import { createRendererWithUniDriver } from '../../utils/test-utils/unit';
import { TimeInputPrivateDriverFactory } from './TimeInput.private.uni.driver';
import TimeInput from '../TimeInput';
describe('TimeInput with disableAutoComplete (mask integration)', function () {
var render = createRendererWithUniDriver(TimeInputPrivateDriverFactory);
beforeAll(function () {
var OriginalDateTimeFormat = Intl.DateTimeFormat;
vi.spyOn(global.Intl, 'DateTimeFormat').mockImplementation(function (locale, options) {
return new OriginalDateTimeFormat(locale, _objectSpread(_objectSpread({}, options), {}, {
numberingSystem: 'latn'
}));
});
});
afterAll(function () {
vi.restoreAllMocks();
});
// The mask placeholder character `_` (and similar) lands in
// `e.target.value` when the user types through the mask. These tests use
// the driver's setValue helper to feed those values directly so
// TimeInput's logic is exercised in isolation. (Attaching `withMask` in
// jsdom does not faithfully reproduce real-browser keystroke flow due to
// the mask's `value` setter override; the integration block below covers
// what we can reliably assert with the mask actually attached.)
describe('mount', function () {
it('does not pre-fill the closest-time slot when disableAutoComplete is set and no value prop is given', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
var _render, driver;
return _regeneratorRuntime.wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
Date.now = vi.fn(function () {
return new Date('2021-01-01 12:18').valueOf();
});
_render = render(/*#__PURE__*/React.createElement(TimeInput, {
disableAutoComplete: true,
locale: "en-GB",
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 38,
columnNumber: 9
}
})), driver = _render.driver;
_context.t0 = expect;
_context.next = 5;
return driver.getInputValue();
case 5:
_context.t1 = _context.sent;
(0, _context.t0)(_context.t1).toBe('');
case 7:
case "end":
return _context.stop();
}
}, _callee);
})));
it('pre-fills the closest-time slot when disableAutoComplete is NOT set (default behavior unchanged)', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
var _render2, driver;
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) switch (_context2.prev = _context2.next) {
case 0:
Date.now = vi.fn(function () {
return new Date('2021-01-01 12:18').valueOf();
});
_render2 = render(/*#__PURE__*/React.createElement(TimeInput, {
locale: "en-GB",
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 46,
columnNumber: 33
}
})), driver = _render2.driver;
_context2.t0 = expect;
_context2.next = 5;
return driver.getInputValue();
case 5:
_context2.t1 = _context2.sent;
(0, _context2.t0)(_context2.t1).not.toBe('');
case 7:
case "end":
return _context2.stop();
}
}, _callee2);
})));
it('still renders an explicit value prop when disableAutoComplete is set', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3() {
var _render3, driver;
return _regeneratorRuntime.wrap(function _callee3$(_context3) {
while (1) switch (_context3.prev = _context3.next) {
case 0:
_render3 = render(/*#__PURE__*/React.createElement(TimeInput, {
disableAutoComplete: true,
locale: "en-GB",
value: new Date('2026-04-27 13:15'),
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 53,
columnNumber: 9
}
})), driver = _render3.driver;
_context3.t0 = expect;
_context3.next = 4;
return driver.getInputValue();
case 4:
_context3.t1 = _context3.sent;
(0, _context3.t0)(_context3.t1).toBe('13:15');
case 6:
case "end":
return _context3.stop();
}
}, _callee3);
})));
});
describe('typing a partial value through the mask', function () {
it('highlights the matching dropdown option when the mask emits "10:__"', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee4() {
var _render4, driver;
return _regeneratorRuntime.wrap(function _callee4$(_context4) {
while (1) switch (_context4.prev = _context4.next) {
case 0:
Date.now = vi.fn(function () {
return new Date('2021-01-01 12:18').valueOf();
});
_render4 = render(/*#__PURE__*/React.createElement(TimeInput, {
disableAutoComplete: true,
locale: "en",
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 67,
columnNumber: 33
}
})), driver = _render4.driver;
_context4.next = 4;
return driver.clickOnInput();
case 4:
_context4.next = 6;
return driver.setValue('10:__');
case 6:
_context4.t0 = expect;
_context4.next = 9;
return driver.getHighlightedOption();
case 9:
_context4.t1 = _context4.sent;
(0, _context4.t0)(_context4.t1).toBe('10:00 PM');
case 11:
case "end":
return _context4.stop();
}
}, _callee4);
})));
it('highlights the matching dropdown option when the mask emits "1_:__"', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee5() {
var _render5, driver;
return _regeneratorRuntime.wrap(function _callee5$(_context5) {
while (1) switch (_context5.prev = _context5.next) {
case 0:
Date.now = vi.fn(function () {
return new Date('2021-01-01 12:18').valueOf();
});
_render5 = render(/*#__PURE__*/React.createElement(TimeInput, {
disableAutoComplete: true,
locale: "en",
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 77,
columnNumber: 33
}
})), driver = _render5.driver;
_context5.next = 4;
return driver.clickOnInput();
case 4:
_context5.next = 6;
return driver.setValue('1_:__');
case 6:
_context5.t0 = expect;
_context5.next = 9;
return driver.getHighlightedOption();
case 9:
_context5.t1 = _context5.sent;
(0, _context5.t0)(_context5.t1).toMatch(/^1[0-9:]/);
case 11:
case "end":
return _context5.stop();
}
}, _callee5);
})));
it('highlights the matching 24-hour slot when the mask emits "13:__" with en-GB locale', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee6() {
var _render6, driver;
return _regeneratorRuntime.wrap(function _callee6$(_context6) {
while (1) switch (_context6.prev = _context6.next) {
case 0:
Date.now = vi.fn(function () {
return new Date('2021-01-01 12:18').valueOf();
});
_render6 = render(/*#__PURE__*/React.createElement(TimeInput, {
disableAutoComplete: true,
locale: "en-GB",
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 88,
columnNumber: 9
}
})), driver = _render6.driver;
_context6.next = 4;
return driver.clickOnInput();
case 4:
_context6.next = 6;
return driver.setValue('13:__');
case 6:
_context6.t0 = expect;
_context6.next = 9;
return driver.getHighlightedOption();
case 9:
_context6.t1 = _context6.sent;
(0, _context6.t0)(_context6.t1).toBe('13:00');
case 11:
case "end":
return _context6.stop();
}
}, _callee6);
})));
it('does not append an AM/PM autofill suffix to the visible input when disableAutoComplete is set', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee7() {
var _render7, driver;
return _regeneratorRuntime.wrap(function _callee7$(_context7) {
while (1) switch (_context7.prev = _context7.next) {
case 0:
Date.now = vi.fn(function () {
return new Date('2021-01-01 12:18').valueOf();
});
_render7 = render(/*#__PURE__*/React.createElement(TimeInput, {
disableAutoComplete: true,
locale: "en",
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 99,
columnNumber: 33
}
})), driver = _render7.driver;
_context7.next = 4;
return driver.clickOnInput();
case 4:
_context7.next = 6;
return driver.setValue('10:00');
case 6:
_context7.t0 = expect;
_context7.next = 9;
return driver.getInputValue();
case 9:
_context7.t1 = _context7.sent;
(0, _context7.t0)(_context7.t1).toBe('10:00');
case 11:
case "end":
return _context7.stop();
}
}, _callee7);
})));
});
describe('committing a typed value', function () {
it('commits the typed time on Enter for a complete mask value', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee8() {
var onChange, _render8, driver, lastCall;
return _regeneratorRuntime.wrap(function _callee8$(_context8) {
while (1) switch (_context8.prev = _context8.next) {
case 0:
onChange = vi.fn();
_render8 = render(/*#__PURE__*/React.createElement(TimeInput, {
disableAutoComplete: true,
onChange: onChange,
locale: "en-GB",
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 114,
columnNumber: 9
}
})), driver = _render8.driver;
_context8.next = 4;
return driver.clickOnInput();
case 4:
_context8.next = 6;
return driver.setValue('13:15');
case 6:
_context8.next = 8;
return driver.pressKey('Enter');
case 8:
expect(onChange).toHaveBeenCalled();
lastCall = onChange.mock.calls[onChange.mock.calls.length - 1][0];
expect(lastCall.date).toBeInstanceOf(Date);
expect(lastCall.date.getHours()).toBe(13);
expect(lastCall.date.getMinutes()).toBe(15);
case 13:
case "end":
return _context8.stop();
}
}, _callee8);
})));
it('commits the typed time on blur for a complete mask value', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee9() {
var onChange, _render9, driver, lastCall;
return _regeneratorRuntime.wrap(function _callee9$(_context9) {
while (1) switch (_context9.prev = _context9.next) {
case 0:
onChange = vi.fn();
_render9 = render(/*#__PURE__*/React.createElement(TimeInput, {
disableAutoComplete: true,
onChange: onChange,
locale: "en-GB",
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 131,
columnNumber: 9
}
})), driver = _render9.driver;
_context9.next = 4;
return driver.clickOnInput();
case 4:
_context9.next = 6;
return driver.setValue('13:15');
case 6:
_context9.next = 8;
return driver.confirmValue();
case 8:
expect(onChange).toHaveBeenCalled();
lastCall = onChange.mock.calls[onChange.mock.calls.length - 1][0];
expect(lastCall.date.getHours()).toBe(13);
expect(lastCall.date.getMinutes()).toBe(15);
case 12:
case "end":
return _context9.stop();
}
}, _callee9);
})));
it('commits the typed off-grid time on Enter (e.g. 10:10 with default 15-min step)', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee0() {
var onChange, _render0, driver, lastCall;
return _regeneratorRuntime.wrap(function _callee0$(_context0) {
while (1) switch (_context0.prev = _context0.next) {
case 0:
Date.now = vi.fn(function () {
return new Date('2026-04-27 12:00').valueOf();
});
onChange = vi.fn();
_render0 = render(/*#__PURE__*/React.createElement(TimeInput, {
disableAutoComplete: true,
onChange: onChange,
locale: "en-GB",
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 148,
columnNumber: 9
}
})), driver = _render0.driver;
_context0.next = 5;
return driver.clickOnInput();
case 5:
_context0.next = 7;
return driver.setValue('10:10');
case 7:
_context0.next = 9;
return driver.pressKey('Enter');
case 9:
expect(onChange).toHaveBeenCalled();
lastCall = onChange.mock.calls[onChange.mock.calls.length - 1][0];
expect(lastCall.date.getHours()).toBe(10);
expect(lastCall.date.getMinutes()).toBe(10);
case 13:
case "end":
return _context0.stop();
}
}, _callee0);
})));
it('commits the highlighted slot on Enter when the typed value is partial (mask placeholders present)', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee1() {
var onChange, _render1, driver, lastCall;
return _regeneratorRuntime.wrap(function _callee1$(_context1) {
while (1) switch (_context1.prev = _context1.next) {
case 0:
Date.now = vi.fn(function () {
return new Date('2021-01-01 12:18').valueOf();
});
onChange = vi.fn();
_render1 = render(/*#__PURE__*/React.createElement(TimeInput, {
disableAutoComplete: true,
onChange: onChange,
locale: "en-GB",
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 165,
columnNumber: 9
}
})), driver = _render1.driver;
_context1.next = 5;
return driver.clickOnInput();
case 5:
_context1.next = 7;
return driver.setValue('13:__');
case 7:
_context1.next = 9;
return driver.pressKey('Enter');
case 9:
// The dropdown highlights "13:00" while user types "13:__"; Enter
// accepts the visible highlight (typical combobox UX).
expect(onChange).toHaveBeenCalled();
lastCall = onChange.mock.calls[onChange.mock.calls.length - 1][0];
expect(lastCall.date.getHours()).toBe(13);
expect(lastCall.date.getMinutes()).toBe(0);
case 13:
case "end":
return _context1.stop();
}
}, _callee1);
})));
});
describe('blurring without a complete value', function () {
it('treats an all-placeholder value ("__:__") as empty and clears via onChange(null)', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee10() {
var onChange, _render10, driver;
return _regeneratorRuntime.wrap(function _callee10$(_context10) {
while (1) switch (_context10.prev = _context10.next) {
case 0:
onChange = vi.fn();
_render10 = render(/*#__PURE__*/React.createElement(TimeInput, {
disableAutoComplete: true,
onChange: onChange,
locale: "en-GB",
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 185,
columnNumber: 9
}
})), driver = _render10.driver;
_context10.next = 4;
return driver.clickOnInput();
case 4:
_context10.next = 6;
return driver.setValue('__:__');
case 6:
_context10.next = 8;
return driver.confirmValue();
case 8:
_context10.t0 = expect;
_context10.next = 11;
return driver.hasStatus('error');
case 11:
_context10.t1 = _context10.sent;
(0, _context10.t0)(_context10.t1).toBe(false);
expect(onChange).toHaveBeenLastCalledWith({
date: null
});
case 14:
case "end":
return _context10.stop();
}
}, _callee10);
})));
it('marks status as error when blurring on a partial value with no matching highlight', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee11() {
var invalidMessage, _render11, driver;
return _regeneratorRuntime.wrap(function _callee11$(_context11) {
while (1) switch (_context11.prev = _context11.next) {
case 0:
invalidMessage = 'Enter a valid time';
_render11 = render(/*#__PURE__*/React.createElement(TimeInput, {
disableAutoComplete: true,
locale: "en-GB",
invalidMessage: invalidMessage,
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 200,
columnNumber: 9
}
})), driver = _render11.driver;
_context11.next = 4;
return driver.clickOnInput();
case 4:
_context11.next = 6;
return driver.setValue('29:__');
case 6:
_context11.next = 8;
return driver.confirmValue();
case 8:
_context11.t0 = expect;
_context11.next = 11;
return driver.hasStatus('error');
case 11:
_context11.t1 = _context11.sent;
(0, _context11.t0)(_context11.t1).toBe(true);
case 13:
case "end":
return _context11.stop();
}
}, _callee11);
})));
it('does not leak "Invalid Date" text into the input on blur of a partial value', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee12() {
var _render12, driver;
return _regeneratorRuntime.wrap(function _callee12$(_context12) {
while (1) switch (_context12.prev = _context12.next) {
case 0:
_render12 = render(/*#__PURE__*/React.createElement(TimeInput, {
disableAutoComplete: true,
locale: "en-GB",
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 217,
columnNumber: 9
}
})), driver = _render12.driver;
_context12.next = 3;
return driver.clickOnInput();
case 3:
_context12.next = 5;
return driver.setValue('10:__');
case 5:
_context12.next = 7;
return driver.confirmValue();
case 7:
_context12.t0 = expect;
_context12.next = 10;
return driver.getInputValue();
case 10:
_context12.t1 = _context12.sent;
(0, _context12.t0)(_context12.t1).not.toMatch(/Invalid|NaN/);
case 12:
case "end":
return _context12.stop();
}
}, _callee12);
})));
});
describe('integration: real mask attached via inputRef', function () {
it('renders an external value prop through the mask without state/DOM divergence', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee13() {
var maskRef, _render13, container, input;
return _regeneratorRuntime.wrap(function _callee13$(_context13) {
while (1) switch (_context13.prev = _context13.next) {
case 0:
maskRef = withMask('99:99', {
placeholder: '_',
showMaskOnHover: false
});
_render13 = render(/*#__PURE__*/React.createElement(TimeInput, {
inputRef: maskRef,
disableAutoComplete: true,
locale: "en-GB",
value: new Date('2026-04-27 10:15'),
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 235,
columnNumber: 9
}
})), container = _render13.container;
input = container.querySelector('input'); // The mask format "99:99" matches the en-GB locale's HH:MM rendering;
// no AM/PM suffix would be added (and disableAutoComplete also blocks
// any suffix), so state and DOM agree.
expect(input.value).toBe('10:15');
case 4:
case "end":
return _context13.stop();
}
}, _callee13);
})));
it('does not pre-fill the input with closest-time when mask is attached and no value prop is provided', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee14() {
var maskRef, _render14, container, input;
return _regeneratorRuntime.wrap(function _callee14$(_context14) {
while (1) switch (_context14.prev = _context14.next) {
case 0:
maskRef = withMask('99:99', {
placeholder: '_',
showMaskOnHover: false
});
_render14 = render(/*#__PURE__*/React.createElement(TimeInput, {
inputRef: maskRef,
disableAutoComplete: true,
locale: "en-GB",
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 256,
columnNumber: 9
}
})), container = _render14.container;
input = container.querySelector('input'); // No closest-time digits prefilled. (In jsdom the mask isn't fully
// applied so the value is empty; in a real browser the mask shows
// `__:__`. Either way, no digits.)
expect(input.value).not.toMatch(/\d/);
case 4:
case "end":
return _context14.stop();
}
}, _callee14);
})));
});
});