import React, { useState } from 'react' import { render } from '@testing-library/react' import userEvent from '@testing-library/user-event' import '@testing-library/jest-dom/extend-expect' import TimeField from './TimeField' interface TimeProps { hours?: number ignoredKeys?: string[] minutes?: number twelveHourClock?: boolean value?: any isIOS?: boolean } const TestApp = ({ value: initialValue, ...props }: TimeProps) => { const [value, setValue] = useState(initialValue) return } const setup = ({ hours, minutes, ...props } : TimeProps) => { const testApp = render() const hourInput = testApp.queryByLabelText('Hours') const minuteInput = testApp.queryByLabelText('Minutes') const meridiemInput = testApp.queryByLabelText('AM/PM') return { hourInput, minuteInput, meridiemInput, ...testApp } } // 0 padding it('left pads 0 for single digit hours', () => { const { hourInput } = setup({ hours: 1 }) expect(hourInput).toHaveValue('01') }) it('doesnt pad double digit hours', () => { const { hourInput } = setup({ hours: 11 }) expect(hourInput).toHaveValue('11') }) it('left pads 0 for single digit minutes', () => { const { minuteInput } = setup({ minutes: 3 }) expect(minuteInput).toHaveValue('03') }) it('doesnt pad double digit minutes', () => { const { minuteInput } = setup({ minutes: 35 }) expect(minuteInput).toHaveValue('35') }) // hour display it('displays 13 hours as 01 hours for 12 hour clock', () => { const { hourInput } = setup({ hours: 13 }) expect(hourInput).toHaveValue('01') }) it('displays 0 hours as 12 hours for 12 hour clock', () => { const { hourInput } = setup({ hours: 13 }) expect(hourInput).toHaveValue('01') }) it('displays 13 hours as 13 hours for 24 hour clock', () => { const { hourInput } = setup({ hours: 13, twelveHourClock: false }) expect(hourInput).toHaveValue('13') }) // meridiem it('displays the meridiem for 12 hour clock', () => { const { meridiemInput } = setup({ hours: 13 }) expect(meridiemInput).toHaveValue('PM') }) it('does not display the meridiem for 24 hour clock', () => { const { meridiemInput } = setup({ hours: 13, twelveHourClock: false }) expect(meridiemInput).not.toBeInTheDocument() }) // arrow key events it('changes focus to minutes from hours on arrow right', () => { const { hourInput, minuteInput } = setup({ hours: 1, minutes: 30 }) userEvent.type(hourInput, '{arrowright}') expect(minuteInput).toHaveFocus() }) it('changes focus to hours from minutes on arrow left', () => { const { hourInput, minuteInput } = setup({ hours: 1, minutes: 30 }) userEvent.type(minuteInput, '{arrowleft}') expect(hourInput).toHaveFocus() }) it('changes focus to meridiem from minutes on arrow right for 12 hour clock', () => { const { minuteInput, meridiemInput } = setup({ hours: 1, minutes: 30 }) userEvent.type(minuteInput, '{arrowright}') expect(meridiemInput).toHaveFocus() }) it('changes the meridiem on arrow key', () => { const { meridiemInput } = setup({ hours: 13, minutes: 42 }) expect(meridiemInput).toHaveValue('PM') userEvent.type(meridiemInput, '{arrowdown}') expect(meridiemInput).toHaveValue('AM') userEvent.type(meridiemInput, '{arrowup}') expect(meridiemInput).toHaveValue('PM') }) it('does not change the meridiem on arrow key if arrow keys are ignored', () => { const { meridiemInput } = setup({ hours: 13, minutes: 42, ignoredKeys: ['ArrowUp', 'ArrowDown'] }) expect(meridiemInput).toHaveValue('PM') userEvent.type(meridiemInput, '{arrowdown}') expect(meridiemInput).toHaveValue('PM') userEvent.type(meridiemInput, '{arrowup}') expect(meridiemInput).toHaveValue('PM') }) it('changes the value of hours on arrow up or arrow down', () => { const { hourInput } = setup( { hours: 1, minutes: 42 }) expect(hourInput).toHaveValue("01") userEvent.type(hourInput, '{arrowup}') expect(hourInput).toHaveValue("02") }) it('does not change the value of hours on arrow up or arrow down if ignored', () => { const { hourInput } = setup( { hours: 1, minutes: 42, ignoredKeys: ['ArrowUp', 'ArrowDown'] }) expect(hourInput).toHaveValue("01") userEvent.type(hourInput, '{arrowup}') expect(hourInput).toHaveValue("01") userEvent.type(hourInput, '{arrowdown}') expect(hourInput).toHaveValue("01") }) it('does not change the value of minutes on arrow up or arrow down if ignored', () => { const { minuteInput } = setup( { hours: 1, minutes: 42, ignoredKeys: ['ArrowUp', 'ArrowDown'] }) expect(minuteInput).toHaveValue("42") userEvent.type(minuteInput, '{arrowup}') expect(minuteInput).toHaveValue("42") userEvent.type(minuteInput, '{arrowdown}') expect(minuteInput).toHaveValue("42") }) // ios it('renders iOS as a single input', () => { const { container, hourInput, minuteInput, meridiemInput } = setup({ isIOS: true, hours: 13, minutes: 42 }) const singleTimeInput = container.querySelector('[type=time]') expect(singleTimeInput).toHaveValue('13:42') expect(hourInput).not.toBeInTheDocument() expect(minuteInput).not.toBeInTheDocument() expect(meridiemInput).not.toBeInTheDocument() })