UNPKG

wix-style-react

Version:
570 lines (425 loc) 19.8 kB
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); }); }); }); });