Migrated RealTimeUpdatesSettings test to react testing library

This commit is contained in:
Alejandro Celaya 2022-06-06 22:23:21 +02:00
parent 53e15b041d
commit a90c3da7b6
2 changed files with 87 additions and 97 deletions

View file

@ -5,6 +5,7 @@ import { SimpleCard } from '../utils/SimpleCard';
import { FormText } from '../utils/forms/FormText'; import { FormText } from '../utils/forms/FormText';
import { LabeledFormGroup } from '../utils/forms/LabeledFormGroup'; import { LabeledFormGroup } from '../utils/forms/LabeledFormGroup';
import { Settings } from './reducers/settings'; import { Settings } from './reducers/settings';
import { useDomId } from '../utils/helpers/hooks';
interface RealTimeUpdatesProps { interface RealTimeUpdatesProps {
settings: Settings; settings: Settings;
@ -16,39 +17,46 @@ const intervalValue = (interval?: number) => (!interval ? '' : `${interval}`);
export const RealTimeUpdatesSettings = ( export const RealTimeUpdatesSettings = (
{ settings: { realTimeUpdates }, toggleRealTimeUpdates, setRealTimeUpdatesInterval }: RealTimeUpdatesProps, { settings: { realTimeUpdates }, toggleRealTimeUpdates, setRealTimeUpdatesInterval }: RealTimeUpdatesProps,
) => ( ) => {
<SimpleCard title="Real-time updates" className="h-100"> const inputId = useDomId();
<FormGroup>
<ToggleSwitch checked={realTimeUpdates.enabled} onChange={toggleRealTimeUpdates}> return (
Enable or disable real-time updates. <SimpleCard title="Real-time updates" className="h-100">
<FormText> <FormGroup>
Real-time updates are currently being <b>{realTimeUpdates.enabled ? 'processed' : 'ignored'}</b>. <ToggleSwitch checked={realTimeUpdates.enabled} onChange={toggleRealTimeUpdates}>
</FormText> Enable or disable real-time updates.
</ToggleSwitch> <FormText>
</FormGroup> Real-time updates are currently being <b>{realTimeUpdates.enabled ? 'processed' : 'ignored'}</b>.
<LabeledFormGroup </FormText>
noMargin </ToggleSwitch>
label="Real-time updates frequency (in minutes):" </FormGroup>
labelClassName={classNames('form-label', { 'text-muted': !realTimeUpdates.enabled })} <LabeledFormGroup
> noMargin
<Input label="Real-time updates frequency (in minutes):"
type="number" labelClassName={classNames('form-label', { 'text-muted': !realTimeUpdates.enabled })}
min={0} id={inputId}
placeholder="Immediate" >
disabled={!realTimeUpdates.enabled} <Input
value={intervalValue(realTimeUpdates.interval)} type="number"
onChange={({ target }) => setRealTimeUpdatesInterval(Number(target.value))} min={0}
/> placeholder="Immediate"
{realTimeUpdates.enabled && ( disabled={!realTimeUpdates.enabled}
<FormText> value={intervalValue(realTimeUpdates.interval)}
{realTimeUpdates.interval !== undefined && realTimeUpdates.interval > 0 && ( id={inputId}
<span> onChange={({ target }) => setRealTimeUpdatesInterval(Number(target.value))}
Updates will be reflected in the UI every <b>{realTimeUpdates.interval}</b> minute{realTimeUpdates.interval > 1 && 's'}. />
</span> {realTimeUpdates.enabled && (
)} <FormText>
{!realTimeUpdates.interval && 'Updates will be reflected in the UI as soon as they happen.'} {realTimeUpdates.interval !== undefined && realTimeUpdates.interval > 0 && (
</FormText> <span>
)} Updates will be reflected in the UI
</LabeledFormGroup> every <b>{realTimeUpdates.interval}</b> minute{realTimeUpdates.interval > 1 && 's'}.
</SimpleCard> </span>
); )}
{!realTimeUpdates.interval && 'Updates will be reflected in the UI as soon as they happen.'}
</FormText>
)}
</LabeledFormGroup>
</SimpleCard>
);
};

View file

@ -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 { Mock } from 'ts-mockery';
import { Input } from 'reactstrap';
import { FormText } from '../../src/utils/forms/FormText';
import { import {
RealTimeUpdatesSettings as RealTimeUpdatesSettingsOptions, RealTimeUpdatesSettings as RealTimeUpdatesSettingsOptions,
Settings, Settings,
} from '../../src/settings/reducers/settings'; } from '../../src/settings/reducers/settings';
import { RealTimeUpdatesSettings } from '../../src/settings/RealTimeUpdatesSettings'; import { RealTimeUpdatesSettings } from '../../src/settings/RealTimeUpdatesSettings';
import { ToggleSwitch } from '../../src/utils/ToggleSwitch';
import { LabeledFormGroup } from '../../src/utils/forms/LabeledFormGroup';
describe('<RealTimeUpdatesSettings />', () => { describe('<RealTimeUpdatesSettings />', () => {
const toggleRealTimeUpdates = jest.fn(); const toggleRealTimeUpdates = jest.fn();
const setRealTimeUpdatesInterval = jest.fn(); const setRealTimeUpdatesInterval = jest.fn();
let wrapper: ShallowWrapper; const setUp = (realTimeUpdates: Partial<RealTimeUpdatesSettingsOptions> = {}) => ({
const createWrapper = (realTimeUpdates: Partial<RealTimeUpdatesSettingsOptions> = {}) => { user: userEvent.setup(),
const settings = Mock.of<Settings>({ realTimeUpdates }); ...render(
wrapper = shallow(
<RealTimeUpdatesSettings <RealTimeUpdatesSettings
settings={settings} settings={Mock.of<Settings>({ realTimeUpdates })}
toggleRealTimeUpdates={toggleRealTimeUpdates} toggleRealTimeUpdates={toggleRealTimeUpdates}
setRealTimeUpdatesInterval={setRealTimeUpdatesInterval} setRealTimeUpdatesInterval={setRealTimeUpdatesInterval}
/>, />,
); ),
});
return wrapper;
};
afterEach(jest.clearAllMocks); afterEach(jest.clearAllMocks);
afterEach(() => wrapper?.unmount());
it('renders enabled real time updates as expected', () => { it('renders enabled real time updates as expected', () => {
const wrapper = createWrapper({ enabled: true }); setUp({ enabled: true });
const toggle = wrapper.find(ToggleSwitch);
const label = wrapper.find(LabeledFormGroup);
const input = wrapper.find(Input);
const formText = wrapper.find(FormText);
expect(toggle.prop('checked')).toEqual(true); expect(screen.getByLabelText(/^Enable or disable real-time updates./)).toBeChecked();
expect(toggle.html()).toContain('processed'); expect(screen.getByText(/^Real-time updates are currently being/)).toHaveTextContent('processed');
expect(toggle.html()).not.toContain('ignored'); expect(screen.getByText(/^Real-time updates are currently being/)).not.toHaveTextContent('ignored');
expect(label.prop('labelClassName')).not.toContain('text-muted'); expect(screen.getByText('Real-time updates frequency (in minutes):')).not.toHaveAttribute(
expect(input.prop('disabled')).toEqual(false); 'class',
expect(formText).toHaveLength(2); 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', () => { it('renders disabled real time updates as expected', () => {
const wrapper = createWrapper({ enabled: false }); setUp({ enabled: false });
const toggle = wrapper.find(ToggleSwitch);
const label = wrapper.find(LabeledFormGroup);
const input = wrapper.find(Input);
const formText = wrapper.find(FormText);
expect(toggle.prop('checked')).toEqual(false); expect(screen.getByLabelText(/^Enable or disable real-time updates./)).not.toBeChecked();
expect(toggle.html()).not.toContain('processed'); expect(screen.getByText(/^Real-time updates are currently being/)).not.toHaveTextContent('processed');
expect(toggle.html()).toContain('ignored'); expect(screen.getByText(/^Real-time updates are currently being/)).toHaveTextContent('ignored');
expect(label.prop('labelClassName')).toContain('text-muted'); expect(screen.getByText('Real-time updates frequency (in minutes):')).toHaveAttribute(
expect(input.prop('disabled')).toEqual(true); 'class',
expect(formText).toHaveLength(1); 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([ it.each([
@ -67,43 +57,35 @@ describe('<RealTimeUpdatesSettings />', () => {
[10, 'minutes'], [10, 'minutes'],
[100, 'minutes'], [100, 'minutes'],
])('shows expected children when interval is greater than 0', (interval, minutesWord) => { ])('shows expected children when interval is greater than 0', (interval, minutesWord) => {
const wrapper = createWrapper({ enabled: true, interval }); setUp({ enabled: true, interval });
const span = wrapper.find('span');
const input = wrapper.find(Input);
expect(span).toHaveLength(1); expect(screen.getByText(/^Updates will be reflected in the UI every/)).toHaveTextContent(
expect(span.html()).toEqual( `${interval} ${minutesWord}`,
`<span>Updates will be reflected in the UI every <b>${interval}</b> ${minutesWord}.</span>`,
); );
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) => { it.each([[undefined], [0]])('shows expected children when interval is 0 or undefined', (interval) => {
const wrapper = createWrapper({ enabled: true, interval }); setUp({ enabled: true, interval });
const span = wrapper.find('span');
const formText = wrapper.find(FormText).at(1);
const input = wrapper.find(Input);
expect(span).toHaveLength(0); expect(screen.queryByText(/^Updates will be reflected in the UI every/)).not.toBeInTheDocument();
expect(formText.html()).toContain('Updates will be reflected in the UI as soon as they happen.'); expect(screen.getByText('Updates will be reflected in the UI as soon as they happen.')).toBeInTheDocument();
expect(input.prop('value')).toEqual('');
}); });
it('updates real time updates on input change', () => { it('updates real time updates when typing on input', async () => {
const wrapper = createWrapper(); const { user } = setUp({ enabled: true });
const input = wrapper.find(Input);
expect(setRealTimeUpdatesInterval).not.toHaveBeenCalled(); expect(setRealTimeUpdatesInterval).not.toHaveBeenCalled();
input.simulate('change', { target: { value: '10' } }); await user.type(screen.getByLabelText('Real-time updates frequency (in minutes):'), '5');
expect(setRealTimeUpdatesInterval).toHaveBeenCalledWith(10); expect(setRealTimeUpdatesInterval).toHaveBeenCalledWith(5);
}); });
it('toggles real time updates on switch change', () => { it('toggles real time updates on switch change', async () => {
const wrapper = createWrapper(); const { user } = setUp({ enabled: true });
const toggle = wrapper.find(ToggleSwitch);
expect(toggleRealTimeUpdates).not.toHaveBeenCalled(); expect(toggleRealTimeUpdates).not.toHaveBeenCalled();
toggle.simulate('change'); await user.click(screen.getByText(/^Enable or disable real-time updates./));
expect(toggleRealTimeUpdates).toHaveBeenCalled(); expect(toggleRealTimeUpdates).toHaveBeenCalled();
}); });
}); });