diff --git a/src/settings/RealTimeUpdatesSettings.tsx b/src/settings/RealTimeUpdatesSettings.tsx index a4218b5a..f587baa8 100644 --- a/src/settings/RealTimeUpdatesSettings.tsx +++ b/src/settings/RealTimeUpdatesSettings.tsx @@ -5,6 +5,7 @@ import { SimpleCard } from '../utils/SimpleCard'; import { FormText } from '../utils/forms/FormText'; import { LabeledFormGroup } from '../utils/forms/LabeledFormGroup'; import { Settings } from './reducers/settings'; +import { useDomId } from '../utils/helpers/hooks'; interface RealTimeUpdatesProps { settings: Settings; @@ -16,39 +17,46 @@ const intervalValue = (interval?: number) => (!interval ? '' : `${interval}`); export const RealTimeUpdatesSettings = ( { settings: { realTimeUpdates }, toggleRealTimeUpdates, setRealTimeUpdatesInterval }: RealTimeUpdatesProps, -) => ( - - - - Enable or disable real-time updates. - - Real-time updates are currently being {realTimeUpdates.enabled ? 'processed' : 'ignored'}. - - - - - setRealTimeUpdatesInterval(Number(target.value))} - /> - {realTimeUpdates.enabled && ( - - {realTimeUpdates.interval !== undefined && realTimeUpdates.interval > 0 && ( - - Updates will be reflected in the UI every {realTimeUpdates.interval} minute{realTimeUpdates.interval > 1 && 's'}. - - )} - {!realTimeUpdates.interval && 'Updates will be reflected in the UI as soon as they happen.'} - - )} - - -); +) => { + const inputId = useDomId(); + + return ( + + + + Enable or disable real-time updates. + + Real-time updates are currently being {realTimeUpdates.enabled ? 'processed' : 'ignored'}. + + + + + setRealTimeUpdatesInterval(Number(target.value))} + /> + {realTimeUpdates.enabled && ( + + {realTimeUpdates.interval !== undefined && realTimeUpdates.interval > 0 && ( + + Updates will be reflected in the UI + every {realTimeUpdates.interval} minute{realTimeUpdates.interval > 1 && 's'}. + + )} + {!realTimeUpdates.interval && 'Updates will be reflected in the UI as soon as they happen.'} + + )} + + + ); +}; diff --git a/test/settings/RealTimeUpdatesSettings.test.tsx b/test/settings/RealTimeUpdatesSettings.test.tsx index 170c1de9..947e27e4 100644 --- a/test/settings/RealTimeUpdatesSettings.test.tsx +++ b/test/settings/RealTimeUpdatesSettings.test.tsx @@ -1,64 +1,54 @@ -import { shallow, ShallowWrapper } from 'enzyme'; +import userEvent from '@testing-library/user-event'; +import { render, screen } from '@testing-library/react'; import { Mock } from 'ts-mockery'; -import { Input } from 'reactstrap'; -import { FormText } from '../../src/utils/forms/FormText'; import { RealTimeUpdatesSettings as RealTimeUpdatesSettingsOptions, Settings, } from '../../src/settings/reducers/settings'; import { RealTimeUpdatesSettings } from '../../src/settings/RealTimeUpdatesSettings'; -import { ToggleSwitch } from '../../src/utils/ToggleSwitch'; -import { LabeledFormGroup } from '../../src/utils/forms/LabeledFormGroup'; describe('', () => { const toggleRealTimeUpdates = jest.fn(); const setRealTimeUpdatesInterval = jest.fn(); - let wrapper: ShallowWrapper; - const createWrapper = (realTimeUpdates: Partial = {}) => { - const settings = Mock.of({ realTimeUpdates }); - - wrapper = shallow( + const setUp = (realTimeUpdates: Partial = {}) => ({ + user: userEvent.setup(), + ...render( ({ realTimeUpdates })} toggleRealTimeUpdates={toggleRealTimeUpdates} setRealTimeUpdatesInterval={setRealTimeUpdatesInterval} />, - ); - - return wrapper; - }; + ), + }); afterEach(jest.clearAllMocks); - afterEach(() => wrapper?.unmount()); it('renders enabled real time updates as expected', () => { - const wrapper = createWrapper({ enabled: true }); - const toggle = wrapper.find(ToggleSwitch); - const label = wrapper.find(LabeledFormGroup); - const input = wrapper.find(Input); - const formText = wrapper.find(FormText); + setUp({ enabled: true }); - expect(toggle.prop('checked')).toEqual(true); - expect(toggle.html()).toContain('processed'); - expect(toggle.html()).not.toContain('ignored'); - expect(label.prop('labelClassName')).not.toContain('text-muted'); - expect(input.prop('disabled')).toEqual(false); - expect(formText).toHaveLength(2); + expect(screen.getByLabelText(/^Enable or disable real-time updates./)).toBeChecked(); + expect(screen.getByText(/^Real-time updates are currently being/)).toHaveTextContent('processed'); + expect(screen.getByText(/^Real-time updates are currently being/)).not.toHaveTextContent('ignored'); + expect(screen.getByText('Real-time updates frequency (in minutes):')).not.toHaveAttribute( + 'class', + expect.stringContaining('text-muted'), + ); + expect(screen.getByLabelText('Real-time updates frequency (in minutes):')).not.toHaveAttribute('disabled'); + expect(screen.getByText('Updates will be reflected in the UI as soon as they happen.')).toBeInTheDocument(); }); it('renders disabled real time updates as expected', () => { - const wrapper = createWrapper({ enabled: false }); - const toggle = wrapper.find(ToggleSwitch); - const label = wrapper.find(LabeledFormGroup); - const input = wrapper.find(Input); - const formText = wrapper.find(FormText); + setUp({ enabled: false }); - expect(toggle.prop('checked')).toEqual(false); - expect(toggle.html()).not.toContain('processed'); - expect(toggle.html()).toContain('ignored'); - expect(label.prop('labelClassName')).toContain('text-muted'); - expect(input.prop('disabled')).toEqual(true); - expect(formText).toHaveLength(1); + expect(screen.getByLabelText(/^Enable or disable real-time updates./)).not.toBeChecked(); + expect(screen.getByText(/^Real-time updates are currently being/)).not.toHaveTextContent('processed'); + expect(screen.getByText(/^Real-time updates are currently being/)).toHaveTextContent('ignored'); + expect(screen.getByText('Real-time updates frequency (in minutes):')).toHaveAttribute( + 'class', + expect.stringContaining('text-muted'), + ); + expect(screen.getByLabelText('Real-time updates frequency (in minutes):')).toHaveAttribute('disabled'); + expect(screen.queryByText('Updates will be reflected in the UI as soon as they happen.')).not.toBeInTheDocument(); }); it.each([ @@ -67,43 +57,35 @@ describe('', () => { [10, 'minutes'], [100, 'minutes'], ])('shows expected children when interval is greater than 0', (interval, minutesWord) => { - const wrapper = createWrapper({ enabled: true, interval }); - const span = wrapper.find('span'); - const input = wrapper.find(Input); + setUp({ enabled: true, interval }); - expect(span).toHaveLength(1); - expect(span.html()).toEqual( - `Updates will be reflected in the UI every ${interval} ${minutesWord}.`, + expect(screen.getByText(/^Updates will be reflected in the UI every/)).toHaveTextContent( + `${interval} ${minutesWord}`, ); - expect(input.prop('value')).toEqual(`${interval}`); + expect(screen.getByLabelText('Real-time updates frequency (in minutes):')).toHaveValue(interval); + expect(screen.queryByText('Updates will be reflected in the UI as soon as they happen.')).not.toBeInTheDocument(); }); it.each([[undefined], [0]])('shows expected children when interval is 0 or undefined', (interval) => { - const wrapper = createWrapper({ enabled: true, interval }); - const span = wrapper.find('span'); - const formText = wrapper.find(FormText).at(1); - const input = wrapper.find(Input); + setUp({ enabled: true, interval }); - expect(span).toHaveLength(0); - expect(formText.html()).toContain('Updates will be reflected in the UI as soon as they happen.'); - expect(input.prop('value')).toEqual(''); + expect(screen.queryByText(/^Updates will be reflected in the UI every/)).not.toBeInTheDocument(); + expect(screen.getByText('Updates will be reflected in the UI as soon as they happen.')).toBeInTheDocument(); }); - it('updates real time updates on input change', () => { - const wrapper = createWrapper(); - const input = wrapper.find(Input); + it('updates real time updates when typing on input', async () => { + const { user } = setUp({ enabled: true }); expect(setRealTimeUpdatesInterval).not.toHaveBeenCalled(); - input.simulate('change', { target: { value: '10' } }); - expect(setRealTimeUpdatesInterval).toHaveBeenCalledWith(10); + await user.type(screen.getByLabelText('Real-time updates frequency (in minutes):'), '5'); + expect(setRealTimeUpdatesInterval).toHaveBeenCalledWith(5); }); - it('toggles real time updates on switch change', () => { - const wrapper = createWrapper(); - const toggle = wrapper.find(ToggleSwitch); + it('toggles real time updates on switch change', async () => { + const { user } = setUp({ enabled: true }); expect(toggleRealTimeUpdates).not.toHaveBeenCalled(); - toggle.simulate('change'); + await user.click(screen.getByText(/^Enable or disable real-time updates./)); expect(toggleRealTimeUpdates).toHaveBeenCalled(); }); });