wix-style-react
Version:
570 lines (425 loc) • 19.8 kB
JavaScript
import React from 'react';
import { act } from 'react-dom/test-utils';
import { createRendererWithUniDriver } from '../../../test/utils/unit';
import { TimeInputNextPrivateDriverFactory } from './TimeInputNext.private.uni.driver';
import TimeInputNext, {
DEFAULT_STEP,
DEFAULT_TIME_STYLE,
} from '../TimeInputNext';
import { getClosestTimeSlot, getTimeSlots } from '../TimeInputNextUtils';
import WixStyleReactEnvironmentProvider from '../../WixStyleReactEnvironmentProvider';
describe(TimeInputNext.displayName, () => {
const render = createRendererWithUniDriver(TimeInputNextPrivateDriverFactory);
describe('onChange', () => {
it(`should call onChange with selected date as a parameter [when] choosing second time slot in a list`, async () => {
const onChange = jest.fn();
const value = new Date('2020-01-01 00:00');
const { driver } = render(
<TimeInputNext onChange={onChange} value={value} />,
);
const timeSlots = getTimeSlots({
value,
timeStyle: DEFAULT_TIME_STYLE,
locale: 'en',
step: DEFAULT_STEP,
});
await driver.clickOnInput();
await driver.selectOptionAt(1);
expect(onChange).toHaveBeenCalledWith({
date: new Date(timeSlots[1].id),
});
});
});
describe('user interactions', () => {
it(`dropdown opens [when] clicked on input`, async () => {
const { driver } = render(<TimeInputNext />);
await driver.clickOnInput();
expect(await driver.isDropdownShown()).toBe(true);
});
it(`dropdown closes [when] option is selected`, async () => {
const { driver } = render(<TimeInputNext />);
await driver.clickOnInput();
await driver.selectOptionAt(1);
expect(await driver.isDropdownShown()).toBe(false);
});
it(`dropdown closes [when] clicked outside`, async () => {
const { driver } = render(<TimeInputNext />);
await driver.clickOnInput();
expect(await driver.isDropdownShown()).toBe(true);
await act(async () => driver.clickOutside());
expect(await driver.isDropdownShown()).toBe(false);
});
it(`input value is set [when] option from dropdown is selected`, async () => {
const value = new Date('2020-05-06 00:00');
const step = 15;
const { driver } = render(<TimeInputNext value={value} step={step} />);
await driver.clickOnInput();
await driver.selectOptionAt(1);
expect(await driver.getInputValue()).toBe('12:15 AM');
});
it('should close dropdown [when] Escape is pressed', async () => {
const { driver } = render(<TimeInputNext />);
await driver.clickOnInput();
await driver.pressKey('Escape');
expect(await driver.isDropdownShown()).toBe(false);
});
it('should close dropdown [when] Enter is pressed and no option is highlighted', async () => {
const { driver } = render(<TimeInputNext />);
await driver.clickOnInput();
await driver.setValue('13');
await driver.pressKey('Enter');
expect(await driver.isDropdownShown()).toBe(false);
});
it('should open dropdown [when] ArrowDown is pressed', async () => {
const { driver } = render(<TimeInputNext />);
await driver.pressKey('ArrowDown');
expect(await driver.isDropdownShown()).toBe(true);
});
it('should not close dropdown and add space to input value [when] option is hovered and Spacebar is pressed', async () => {
const { driver } = render(<TimeInputNext />);
await driver.clickOnInput();
await driver.setValue('2');
await driver.pressKey('Spacebar');
expect(await driver.isDropdownShown()).toBe(true);
});
it('should stop selecting option [when] there is no matching value to input value', async () => {
const { driver } = render(
<TimeInputNext value={new Date('2021-09-10 12:30')} />,
);
await driver.clickOnInput();
await driver.setValue('');
expect(await driver.getSelectedOptionId()).toBe(null);
});
it('should open dropdown [when] value is selected with `enter` and user types again', async () => {
const { driver } = render(<TimeInputNext />);
await driver.clickOnInput();
await driver.setValue('2');
await driver.pressKey('Enter');
expect(await driver.isDropdownShown()).toBe(false);
await driver.setValue('2');
expect(await driver.isDropdownShown()).toBe(true);
});
it('should fill input with highlighted value [when] input loses focus', async () => {
const { driver } = render(<TimeInputNext />);
await driver.clickOnInput();
await driver.setValue('2:00 P');
await driver.blur();
expect(await driver.getInputValue()).toBe('2:00 PM');
});
it('should close dropdown [when] input loses focus', async () => {
const { driver } = render(<TimeInputNext />);
await driver.clickOnInput();
expect(await driver.isDropdownShown()).toBe(true);
await driver.blur();
expect(await driver.isDropdownShown()).toBe(false);
});
});
describe('ref', () => {
it('should acccess focus method through ref [when] ref is passed to component', async () => {
const myRef = React.createRef();
const { driver } = render(<TimeInputNext ref={myRef} />);
myRef.current.focus();
expect(await driver.isFocused()).toEqual(true);
});
});
describe('properties', () => {
describe('value', () => {
it(`should pass correct Date value to value prop [when] it is passed to value prop`, async () => {
const expectedValue = new Date('2020-05-06 18:45');
const { driver } = render(<TimeInputNext value={expectedValue} />);
expect(await driver.getValue()).toEqual(expectedValue);
});
it('should set input value as a nearest time slot to current time [when] value prop is not defined', async () => {
const { driver } = render(<TimeInputNext step={20} />);
const timeSlots = getTimeSlots({
locale: 'en',
timeStyle: 'short',
step: '20',
});
const expectedValue = getClosestTimeSlot({
value: new Date(),
timeSlots,
});
expect(await driver.getInputValue()).toBe(expectedValue.value);
});
it(`should set value prop [when] value is typed in`, async () => {
const { driver } = render(<TimeInputNext />);
await driver.setValue('12:15');
expect(await driver.getInputValue()).toBe('12:15');
});
it('should update value prop [when] value prop is changed', async () => {
const { driver, rerender } = render(
<TimeInputNext value={new Date('2020-02-02 03:03')} />,
);
rerender(<TimeInputNext value={new Date('2020-02-02 02:02')} />);
expect(await driver.getInputValue()).toBe('2:02 AM');
});
});
describe('disable', () => {
it(`should disable input [when] disable prop is true`, async () => {
const { driver } = render(<TimeInputNext disabled />);
expect(await driver.isDisabled()).toBe(true);
});
});
describe('readOnly', () => {
it(`should not open dropdown on input click [when] readOnly prop is true`, async () => {
const { driver } = render(<TimeInputNext readOnly />);
await driver.clickOnInput();
expect(await driver.isDropdownShown()).toBe(false);
});
});
describe('statusMessage', () => {
it('should display error status [when] status prop is set to `error`', async () => {
const status = 'error';
const statusMessage = 'Error message';
const { driver } = render(
<TimeInputNext status={status} statusMessage={statusMessage} />,
);
expect(await driver.hasStatus(status)).toBe(true);
expect(await driver.getStatusMessage()).toBe(statusMessage);
});
it('should not display status [when] status prop is not passed', async () => {
const { driver } = render(<TimeInputNext />);
expect(await driver.hasStatus('error')).toBe(false);
expect(await driver.getStatusMessage()).toBeNull();
});
});
describe('timeStyle', () => {
it('should set timeStyle prop to short [when] timeStyle prop is `short`', async () => {
const { driver } = render(<TimeInputNext />);
expect(await driver.getTimeStyle()).toBe('short');
});
it('should set timeStyle prop to long [when] timeStyle prop is `long`', async () => {
const { driver } = render(<TimeInputNext timeStyle="long" />);
expect(await driver.getTimeStyle()).toBe('long');
});
});
describe('locale', () => {
it('should set locale prop to `hi` [when] locale prop is set to `hi`', async () => {
const { driver } = render(<TimeInputNext locale="hi" />);
expect(await driver.getLocale()).toBe('hi');
});
it('should set the locale prop to `es` [when] locale prop is set to `es` in WixStyleReactEnvironmentProvider', async () => {
const { driver } = render(
<WixStyleReactEnvironmentProvider locale="es">
<TimeInputNext />
</WixStyleReactEnvironmentProvider>,
);
expect(await driver.getLocale()).toBe('es');
});
it('should set locale prop instead of WixStyleReactEnvironmentProvider [when] given both', async () => {
const { driver } = render(
<WixStyleReactEnvironmentProvider locale="es">
<TimeInputNext locale="lt" />
</WixStyleReactEnvironmentProvider>,
);
expect(await driver.getLocale()).toBe('lt');
});
it('should set locale prop to `en` [when] locale prop is not set', async () => {
const { driver } = render(<TimeInputNext />);
expect(await driver.getLocale()).toBe('en');
});
});
});
describe('autocomplete', () => {
describe('with en locale (12 hour format) and current time is 12:18 PM', () => {
it("shouldn't highlight anything [when] 0 is typed in", async () => {
Date.now = jest.fn(() => new Date('2021-01-01 12:18').valueOf());
const { driver } = render(<TimeInputNext locale="en" />);
await driver.clickOnInput();
await driver.setValue('0');
expect(await driver.getHighlightedOption()).toBe(null);
});
it('should highlight 12:30 PM [when] 1 is typed in', async () => {
Date.now = jest.fn(() => new Date('2021-01-01 12:18').valueOf());
const { driver } = render(<TimeInputNext locale="en" />);
await driver.clickOnInput();
await driver.setValue('1');
expect(await driver.getHighlightedOption()).toBe('12:30 PM');
});
it('should highlight 2:00 PM [when] 2 is typed in', async () => {
Date.now = jest.fn(() => new Date('2021-01-01 12:18').valueOf());
const { driver } = render(<TimeInputNext locale="en" />);
await driver.clickOnInput();
await driver.setValue('2');
expect(await driver.getHighlightedOption()).toBe('2:00 PM');
});
it('should highlight 1:00 PM [when] 01 is typed in', async () => {
Date.now = jest.fn(() => new Date('2021-01-01 12:18').valueOf());
const { driver } = render(<TimeInputNext locale="en" />);
await driver.clickOnInput();
await driver.setValue('01');
expect(await driver.getHighlightedOption()).toBe('1:00 PM');
});
it("shouldn't highlight anything [when] 18 is typed in", async () => {
Date.now = jest.fn(() => new Date('2021-01-01 12:18').valueOf());
const { driver } = render(<TimeInputNext locale="en" />);
await driver.clickOnInput();
await driver.setValue('18');
expect(await driver.getHighlightedOption()).toBe(null);
});
it('should highlight 1:15 PM [when] 1:1 is typed in', async () => {
Date.now = jest.fn(() => new Date('2021-01-01 12:18').valueOf());
const { driver } = render(<TimeInputNext locale="en" />);
await driver.clickOnInput();
await driver.setValue('1:1');
expect(await driver.getHighlightedOption()).toBe('1:15 PM');
});
it('should highlight 1:15 PM [when] 01:1 is typed in', async () => {
Date.now = jest.fn(() => new Date('2021-01-01 12:18').valueOf());
const { driver } = render(<TimeInputNext locale="en" />);
await driver.clickOnInput();
await driver.setValue('01:1');
expect(await driver.getHighlightedOption()).toBe('1:15 PM');
});
it("shouldn't highlight anything [when] 2:40 is typed in and step prop is set to 15", async () => {
Date.now = jest.fn(() => new Date('2021-01-01 12:18').valueOf());
const { driver } = render(<TimeInputNext locale="en" step={15} />);
await driver.clickOnInput();
await driver.setValue('2:40');
expect(await driver.getHighlightedOption()).toBe(null);
});
});
describe('with en locale (12 hour format) and current time is 11:18 PM', () => {
it('should highlight 2:00 AM [when] 2 is typed in', async () => {
Date.now = jest.fn(() => new Date('2021-01-01 23:18').valueOf());
const { driver } = render(<TimeInputNext locale="en" />);
await driver.clickOnInput();
await driver.setValue('2');
expect(await driver.getHighlightedOption()).toBe('2:00 AM');
});
it('should highlight 1:00 AM [when] 01 is typed in', async () => {
Date.now = jest.fn(() => new Date('2021-01-01 23:18').valueOf());
const { driver } = render(<TimeInputNext locale="en" />);
await driver.clickOnInput();
await driver.setValue('01');
expect(await driver.getHighlightedOption()).toBe('1:00 AM');
});
it('should highlight 10:15 AM [when] 10:15 is typed in', async () => {
Date.now = jest.fn(() => new Date('2021-01-01 23:18').valueOf());
const { driver } = render(<TimeInputNext locale="en" />);
await driver.clickOnInput();
await driver.setValue('10:15');
expect(await driver.getHighlightedOption()).toBe('10:15 AM');
});
});
describe('with lt locale (24 hour format) and current time is 09:12', () => {
it('should highlight 10:00 [when] 1 is typed in', async () => {
Date.now = jest.fn(() => new Date('2021-01-01 09:12').valueOf());
const { driver } = render(<TimeInputNext locale="lt" />);
await driver.clickOnInput();
await driver.setValue('1');
expect(await driver.getHighlightedOption()).toBe('10:00');
});
it('should highlight 01:00 [when] 01 is typed in', async () => {
Date.now = jest.fn(() => new Date('2021-01-01 09:12').valueOf());
const { driver } = render(<TimeInputNext locale="lt" />);
await driver.clickOnInput();
await driver.setValue('01');
expect(await driver.getHighlightedOption()).toBe('01:00');
});
it('should highlight 12:00 [when] 12 is typed in', async () => {
Date.now = jest.fn(() => new Date('2021-01-01 09:12').valueOf());
const { driver } = render(<TimeInputNext locale="lt" />);
await driver.clickOnInput();
await driver.setValue('12');
expect(await driver.getHighlightedOption()).toBe('12:00');
});
it('should highlight 01:15 [when] 1:1 is typed in', async () => {
Date.now = jest.fn(() => new Date('2021-01-01 09:12').valueOf());
const { driver } = render(<TimeInputNext locale="lt" />);
await driver.clickOnInput();
await driver.setValue('1:1');
expect(await driver.getHighlightedOption()).toBe('01:15');
});
it("shouldn't highlight anything [when] 1:10 is typed in and step prop is set to 15", async () => {
Date.now = jest.fn(() => new Date('2021-01-01 09:12').valueOf());
const { driver } = render(<TimeInputNext locale="lt" step={15} />);
await driver.clickOnInput();
await driver.setValue('1:10');
expect(await driver.getHighlightedOption()).toBe(null);
});
});
describe('with locale where time has prefix and current time is 07:12 AM', () => {
it('should highlight 下午6:00 [when] 6 is typed in and locale is set to zh', async () => {
Date.now = jest.fn(() => new Date('2021-01-01 07:12').valueOf());
const { driver } = render(<TimeInputNext locale="zh" />);
await driver.clickOnInput();
await driver.setValue('6');
expect(await driver.getHighlightedOption()).toBe('下午6:00');
});
it('should highlight 오후 6:00 [when] 6 is typed in and locale is set to ko', async () => {
Date.now = jest.fn(() => new Date('2021-01-01 07:12').valueOf());
const { driver } = render(<TimeInputNext locale="ko" />);
await driver.clickOnInput();
await driver.setValue('6');
expect(await driver.getHighlightedOption()).toBe('오후 6:00');
});
it('should highlight 오전 8:00 [when] 08 is typed in and locale is set to ko', async () => {
Date.now = jest.fn(() => new Date('2021-01-01 07:12').valueOf());
const { driver } = render(<TimeInputNext locale="ko" />);
await driver.clickOnInput();
await driver.setValue('08');
expect(await driver.getHighlightedOption()).toBe('오전 8:00');
});
it('should highlight 上午8:00 [when] 上午08 is typed in and locale is set to zh', async () => {
Date.now = jest.fn(() => new Date('2021-01-01 07:12').valueOf());
const { driver } = render(<TimeInputNext locale="zh" />);
await driver.clickOnInput();
await driver.setValue('上午08');
expect(await driver.getHighlightedOption()).toBe('上午8:00');
});
it('should highlight 上午8:00 [when] 上午8 is typed in and locale is set to zh', async () => {
Date.now = jest.fn(() => new Date('2021-01-01 07:12').valueOf());
const { driver } = render(<TimeInputNext locale="zh" />);
await driver.clickOnInput();
await driver.setValue('上午8');
expect(await driver.getHighlightedOption()).toBe('上午8:00');
});
});
describe('with locale that has dot (.) divider and current time is 07:12', () => {
it('should highlight 13.00 [when] 13 is typed in and locale is set to fi', async () => {
Date.now = jest.fn(() => new Date('2021-01-01 07:12').valueOf());
const { driver } = render(<TimeInputNext locale="fi" />);
await driver.clickOnInput();
await driver.setValue('13');
expect(await driver.getHighlightedOption()).toBe('13.00');
});
});
});
describe('validation', () => {
describe('should set status to `error`', () => {
it.each(['a', '269', '12:8', '15:69'])(
'[when] value is set to %s',
async value => {
const { driver } = render(<TimeInputNext />);
await driver.clickOnInput();
await driver.setValue(value);
expect(await driver.hasStatus('error')).toBe(true);
},
);
});
describe('should not set status to `error`', () => {
it.each([
'上午 ',
'전후 08:12',
'23',
'12',
'5',
'12:',
'12:0',
'15:25',
'09:05 PM',
'10:59 p.m.',
'1000',
'11 PM',
'250',
])('[when] value is set to %s', async value => {
const { driver } = render(<TimeInputNext />);
await driver.clickOnInput();
await driver.setValue(value);
expect(await driver.hasStatus('error')).toBe(false);
});
});
});
});