mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2025-01-10 18:27:25 +03:00
Merge pull request #630 from acelaya-forks/feature/react-testing-lib
Feature/react testing lib
This commit is contained in:
commit
fd4295ade8
6 changed files with 127 additions and 162 deletions
|
@ -12,6 +12,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
* [#616](https://github.com/shlinkio/shlink-web-client/pull/616) Updated to React 18.
|
* [#616](https://github.com/shlinkio/shlink-web-client/pull/616) Updated to React 18.
|
||||||
* [#594](https://github.com/shlinkio/shlink-web-client/pull/594) Updated to a new coding standard.
|
* [#594](https://github.com/shlinkio/shlink-web-client/pull/594) Updated to a new coding standard.
|
||||||
* [#603](https://github.com/shlinkio/shlink-web-client/pull/603) Migrated to new and maintained dependencies to parse CSV<->JSON.
|
* [#603](https://github.com/shlinkio/shlink-web-client/pull/603) Migrated to new and maintained dependencies to parse CSV<->JSON.
|
||||||
|
* [#619](https://github.com/shlinkio/shlink-web-client/pull/619) Introduced react testing library, to progressively replace enzyme.
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
* *Nothing*
|
* *Nothing*
|
||||||
|
|
|
@ -8,7 +8,7 @@ interface SimpleCardProps extends Omit<CardProps, 'title'> {
|
||||||
|
|
||||||
export const SimpleCard = ({ title, children, bodyClassName, ...rest }: SimpleCardProps) => (
|
export const SimpleCard = ({ title, children, bodyClassName, ...rest }: SimpleCardProps) => (
|
||||||
<Card {...rest}>
|
<Card {...rest}>
|
||||||
{title && <CardHeader>{title}</CardHeader>}
|
{title && <CardHeader role="heading">{title}</CardHeader>}
|
||||||
<CardBody className={bodyClassName}>{children}</CardBody>
|
<CardBody className={bodyClassName}>{children}</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,38 +1,40 @@
|
||||||
import { shallow, ShallowWrapper } from 'enzyme';
|
import { fireEvent, render, screen } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import { DropdownItem } from 'reactstrap';
|
|
||||||
import { ShortUrlCreationSettings as ShortUrlsSettings, Settings } from '../../src/settings/reducers/settings';
|
import { ShortUrlCreationSettings as ShortUrlsSettings, Settings } from '../../src/settings/reducers/settings';
|
||||||
import { ShortUrlCreationSettings } from '../../src/settings/ShortUrlCreationSettings';
|
import { ShortUrlCreationSettings } from '../../src/settings/ShortUrlCreationSettings';
|
||||||
import { FormText } from '../../src/utils/forms/FormText';
|
|
||||||
import ToggleSwitch from '../../src/utils/ToggleSwitch';
|
|
||||||
import { DropdownBtn } from '../../src/utils/DropdownBtn';
|
|
||||||
|
|
||||||
describe('<ShortUrlCreationSettings />', () => {
|
describe('<ShortUrlCreationSettings />', () => {
|
||||||
let wrapper: ShallowWrapper;
|
|
||||||
const setShortUrlCreationSettings = jest.fn();
|
const setShortUrlCreationSettings = jest.fn();
|
||||||
const createWrapper = (shortUrlCreation?: ShortUrlsSettings) => {
|
const setUp = (shortUrlCreation?: ShortUrlsSettings) => render(
|
||||||
wrapper = shallow(
|
|
||||||
<ShortUrlCreationSettings
|
<ShortUrlCreationSettings
|
||||||
settings={Mock.of<Settings>({ shortUrlCreation })}
|
settings={Mock.of<Settings>({ shortUrlCreation })}
|
||||||
setShortUrlCreationSettings={setShortUrlCreationSettings}
|
setShortUrlCreationSettings={setShortUrlCreationSettings}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
return wrapper;
|
|
||||||
};
|
|
||||||
|
|
||||||
afterEach(() => wrapper?.unmount());
|
|
||||||
afterEach(jest.clearAllMocks);
|
afterEach(jest.clearAllMocks);
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[{ validateUrls: true }, true],
|
[{ validateUrls: true }, true],
|
||||||
[{ validateUrls: false }, false],
|
[{ validateUrls: false }, false],
|
||||||
[undefined, false],
|
[undefined, false],
|
||||||
])('URL validation switch is toggled if option is true', (shortUrlCreation, expectedChecked) => {
|
])('URL validation switch has proper initial state', (shortUrlCreation, expectedChecked) => {
|
||||||
const wrapper = createWrapper(shortUrlCreation);
|
const matcher = /^Request validation on long URLs when creating new short URLs/;
|
||||||
const urlValidationToggle = wrapper.find(ToggleSwitch).first();
|
|
||||||
|
|
||||||
expect(urlValidationToggle.prop('checked')).toEqual(expectedChecked);
|
setUp(shortUrlCreation);
|
||||||
|
|
||||||
|
const checkbox = screen.getByLabelText(matcher);
|
||||||
|
const label = screen.getByText(matcher);
|
||||||
|
|
||||||
|
if (expectedChecked) {
|
||||||
|
expect(checkbox).toBeChecked();
|
||||||
|
expect(label).toHaveTextContent('Validate URL checkbox will be checked');
|
||||||
|
expect(label).not.toHaveTextContent('Validate URL checkbox will be unchecked');
|
||||||
|
} else {
|
||||||
|
expect(checkbox).not.toBeChecked();
|
||||||
|
expect(label).toHaveTextContent('Validate URL checkbox will be unchecked');
|
||||||
|
expect(label).not.toHaveTextContent('Validate URL checkbox will be checked');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
|
@ -40,32 +42,22 @@ describe('<ShortUrlCreationSettings />', () => {
|
||||||
[{ forwardQuery: false }, false],
|
[{ forwardQuery: false }, false],
|
||||||
[{}, true],
|
[{}, true],
|
||||||
])('forward query switch is toggled if option is true', (shortUrlCreation, expectedChecked) => {
|
])('forward query switch is toggled if option is true', (shortUrlCreation, expectedChecked) => {
|
||||||
const wrapper = createWrapper({ validateUrls: true, ...shortUrlCreation });
|
const matcher = /^Make all new short URLs forward their query params to the long URL/;
|
||||||
const forwardQueryToggle = wrapper.find(ToggleSwitch).last();
|
|
||||||
|
|
||||||
expect(forwardQueryToggle.prop('checked')).toEqual(expectedChecked);
|
setUp({ validateUrls: true, ...shortUrlCreation });
|
||||||
});
|
|
||||||
|
|
||||||
it.each([
|
const checkbox = screen.getByLabelText(matcher);
|
||||||
[{ validateUrls: true }, '<b>Validate URL</b> checkbox will be <b>checked</b>'],
|
const label = screen.getByText(matcher);
|
||||||
[{ validateUrls: false }, '<b>Validate URL</b> checkbox will be <b>unchecked</b>'],
|
|
||||||
[undefined, '<b>Validate URL</b> checkbox will be <b>unchecked</b>'],
|
|
||||||
])('shows expected helper text for URL validation', (shortUrlCreation, expectedText) => {
|
|
||||||
const wrapper = createWrapper(shortUrlCreation);
|
|
||||||
const validateUrlText = wrapper.find(FormText).first();
|
|
||||||
|
|
||||||
expect(validateUrlText.html()).toContain(expectedText);
|
if (expectedChecked) {
|
||||||
});
|
expect(checkbox).toBeChecked();
|
||||||
|
expect(label).toHaveTextContent('Forward query params on redirect checkbox will be checked');
|
||||||
it.each([
|
expect(label).not.toHaveTextContent('Forward query params on redirect checkbox will be unchecked');
|
||||||
[{ forwardQuery: true }, '<b>Forward query params on redirect</b> checkbox will be <b>checked</b>'],
|
} else {
|
||||||
[{ forwardQuery: false }, '<b>Forward query params on redirect</b> checkbox will be <b>unchecked</b>'],
|
expect(checkbox).not.toBeChecked();
|
||||||
[{}, '<b>Forward query params on redirect</b> checkbox will be <b>checked</b>'],
|
expect(label).toHaveTextContent('Forward query params on redirect checkbox will be unchecked');
|
||||||
])('shows expected helper text for query forwarding', (shortUrlCreation, expectedText) => {
|
expect(label).not.toHaveTextContent('Forward query params on redirect checkbox will be checked');
|
||||||
const wrapper = createWrapper({ validateUrls: true, ...shortUrlCreation });
|
}
|
||||||
const forwardQueryText = wrapper.find(FormText).at(1);
|
|
||||||
|
|
||||||
expect(forwardQueryText.html()).toContain(expectedText);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
|
@ -77,47 +69,46 @@ describe('<ShortUrlCreationSettings />', () => {
|
||||||
],
|
],
|
||||||
[undefined, 'Suggest tags starting with input', 'starting with'],
|
[undefined, 'Suggest tags starting with input', 'starting with'],
|
||||||
])('shows expected texts for tags suggestions', (shortUrlCreation, expectedText, expectedHint) => {
|
])('shows expected texts for tags suggestions', (shortUrlCreation, expectedText, expectedHint) => {
|
||||||
const wrapper = createWrapper(shortUrlCreation);
|
setUp(shortUrlCreation);
|
||||||
const hintText = wrapper.find(FormText).last();
|
|
||||||
const dropdown = wrapper.find(DropdownBtn);
|
|
||||||
|
|
||||||
expect(dropdown.prop('text')).toEqual(expectedText);
|
expect(screen.getByRole('button', { name: expectedText })).toBeInTheDocument();
|
||||||
expect(hintText.html()).toContain(expectedHint);
|
expect(screen.getByText(/^The list of suggested tags will contain those/)).toHaveTextContent(expectedHint);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([[true], [false]])('invokes setShortUrlCreationSettings when URL validation toggle value changes', (validateUrls) => {
|
it.each([[true], [false]])('invokes setShortUrlCreationSettings when URL validation toggle value changes', (validateUrls) => {
|
||||||
const wrapper = createWrapper();
|
setUp({ validateUrls });
|
||||||
const urlValidationToggle = wrapper.find(ToggleSwitch).first();
|
|
||||||
|
|
||||||
expect(setShortUrlCreationSettings).not.toHaveBeenCalled();
|
expect(setShortUrlCreationSettings).not.toHaveBeenCalled();
|
||||||
urlValidationToggle.simulate('change', validateUrls);
|
fireEvent.click(screen.getByLabelText(/^Request validation on long URLs when creating new short URLs/));
|
||||||
expect(setShortUrlCreationSettings).toHaveBeenCalledWith({ validateUrls });
|
expect(setShortUrlCreationSettings).toHaveBeenCalledWith({ validateUrls: !validateUrls });
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([[true], [false]])('invokes setShortUrlCreationSettings when forward query toggle value changes', (forwardQuery) => {
|
it.each([[true], [false]])('invokes setShortUrlCreationSettings when forward query toggle value changes', (forwardQuery) => {
|
||||||
const wrapper = createWrapper();
|
setUp({ validateUrls: true, forwardQuery });
|
||||||
const urlValidationToggle = wrapper.find(ToggleSwitch).last();
|
|
||||||
|
|
||||||
expect(setShortUrlCreationSettings).not.toHaveBeenCalled();
|
expect(setShortUrlCreationSettings).not.toHaveBeenCalled();
|
||||||
urlValidationToggle.simulate('change', forwardQuery);
|
fireEvent.click(screen.getByLabelText(/^Make all new short URLs forward their query params to the long URL/));
|
||||||
expect(setShortUrlCreationSettings).toHaveBeenCalledWith(expect.objectContaining({ forwardQuery }));
|
expect(setShortUrlCreationSettings).toHaveBeenCalledWith(expect.objectContaining({ forwardQuery: !forwardQuery }));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('invokes setShortUrlCreationSettings when dropdown value changes', () => {
|
it('invokes setShortUrlCreationSettings when dropdown value changes', async () => {
|
||||||
const wrapper = createWrapper();
|
setUp();
|
||||||
const firstDropdownItem = wrapper.find(DropdownItem).first();
|
|
||||||
const secondDropdownItem = wrapper.find(DropdownItem).last();
|
const clickItem = async (name: string) => {
|
||||||
|
fireEvent.click(screen.getByRole('button', { name: 'Suggest tags starting with input' }));
|
||||||
|
fireEvent.click(await screen.findByRole('menuitem', { name }));
|
||||||
|
};
|
||||||
|
|
||||||
expect(setShortUrlCreationSettings).not.toHaveBeenCalled();
|
expect(setShortUrlCreationSettings).not.toHaveBeenCalled();
|
||||||
|
|
||||||
firstDropdownItem.simulate('click');
|
await clickItem('Suggest tags including input');
|
||||||
expect(setShortUrlCreationSettings).toHaveBeenCalledWith(expect.objectContaining(
|
|
||||||
{ tagFilteringMode: 'startsWith' },
|
|
||||||
));
|
|
||||||
|
|
||||||
secondDropdownItem.simulate('click');
|
|
||||||
expect(setShortUrlCreationSettings).toHaveBeenCalledWith(expect.objectContaining(
|
expect(setShortUrlCreationSettings).toHaveBeenCalledWith(expect.objectContaining(
|
||||||
{ tagFilteringMode: 'includes' },
|
{ tagFilteringMode: 'includes' },
|
||||||
));
|
));
|
||||||
|
|
||||||
|
await clickItem('Suggest tags starting with input');
|
||||||
|
expect(setShortUrlCreationSettings).toHaveBeenCalledWith(expect.objectContaining(
|
||||||
|
{ tagFilteringMode: 'startsWith' },
|
||||||
|
));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,70 +1,43 @@
|
||||||
import { ChangeEvent, PropsWithChildren } from 'react';
|
import { fireEvent, render, screen } from '@testing-library/react';
|
||||||
import { mount, ReactWrapper } from 'enzyme';
|
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import Checkbox from '../../src/utils/Checkbox';
|
import Checkbox from '../../src/utils/Checkbox';
|
||||||
import { BooleanControlProps } from '../../src/utils/BooleanControl';
|
|
||||||
|
|
||||||
describe('<Checkbox />', () => {
|
describe('<Checkbox />', () => {
|
||||||
let wrapped: ReactWrapper;
|
it.each([['foo'], ['bar'], ['baz']])('includes extra class names when provided', (className) => {
|
||||||
|
const { container } = render(<Checkbox className={className} />);
|
||||||
const createComponent = (props: PropsWithChildren<BooleanControlProps> = {}) => {
|
expect(container.firstChild).toHaveAttribute('class', `form-check form-checkbox ${className}`);
|
||||||
wrapped = mount(<Checkbox {...props} />);
|
|
||||||
|
|
||||||
return wrapped;
|
|
||||||
};
|
|
||||||
|
|
||||||
afterEach(() => wrapped?.unmount());
|
|
||||||
|
|
||||||
it('includes extra class names when provided', () => {
|
|
||||||
const classNames = ['foo', 'bar', 'baz'];
|
|
||||||
|
|
||||||
expect.assertions(classNames.length);
|
|
||||||
classNames.forEach((className) => {
|
|
||||||
const wrapped = createComponent({ className });
|
|
||||||
|
|
||||||
expect(wrapped.prop('className')).toContain(className);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('marks input as checked if defined', () => {
|
it.each([[true], [false]])('marks input as checked if defined', (checked) => {
|
||||||
const checkeds = [true, false];
|
render(<Checkbox checked={checked}>Foo</Checkbox>);
|
||||||
|
|
||||||
expect.assertions(checkeds.length);
|
if (checked) {
|
||||||
checkeds.forEach((checked) => {
|
expect(screen.getByLabelText('Foo')).toBeChecked();
|
||||||
const wrapped = createComponent({ checked });
|
} else {
|
||||||
const input = wrapped.find('input');
|
expect(screen.getByLabelText('Foo')).not.toBeChecked();
|
||||||
|
}
|
||||||
expect(input.prop('checked')).toEqual(checked);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders provided children inside the label', () => {
|
it.each([['foo'], ['bar'], ['baz']])('renders provided children inside the label', (children) => {
|
||||||
const labels = ['foo', 'bar', 'baz'];
|
render(<Checkbox>{children}</Checkbox>);
|
||||||
|
expect(screen.getByText(children)).toHaveAttribute('class', 'form-check-label');
|
||||||
expect.assertions(labels.length);
|
|
||||||
labels.forEach((children) => {
|
|
||||||
const wrapped = createComponent({ children });
|
|
||||||
const label = wrapped.find('label');
|
|
||||||
|
|
||||||
expect(label.text()).toEqual(children);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('changes checked status on input change', () => {
|
it.each([[true], [false]])('changes checked status on input change', (checked) => {
|
||||||
const onChange = jest.fn();
|
const onChange = jest.fn();
|
||||||
const e = Mock.of<ChangeEvent<HTMLInputElement>>({ target: { checked: false } });
|
render(<Checkbox onChange={onChange} checked={checked}>Foo</Checkbox>);
|
||||||
const wrapped = createComponent({ checked: true, onChange });
|
|
||||||
const input = wrapped.find('input');
|
|
||||||
|
|
||||||
(input.prop('onChange') as Function)(e);
|
expect(onChange).not.toHaveBeenCalled();
|
||||||
|
fireEvent.click(screen.getByLabelText('Foo'));
|
||||||
expect(onChange).toHaveBeenCalledWith(false, e);
|
expect(onChange).toHaveBeenCalledWith(!checked, expect.anything());
|
||||||
});
|
});
|
||||||
|
|
||||||
it('allows setting inline rendering', () => {
|
it.each([[true], [false]])('allows setting inline rendering', (inline) => {
|
||||||
const wrapped = createComponent({ inline: true });
|
const { container } = render(<Checkbox inline={inline} />);
|
||||||
const control = wrapped.find('.form-check');
|
|
||||||
|
|
||||||
expect(control.prop('style')).toEqual({ display: 'inline-block' });
|
if (inline) {
|
||||||
|
expect(container.firstChild).toHaveAttribute('style', 'display: inline-block;');
|
||||||
|
} else {
|
||||||
|
expect(container.firstChild).not.toHaveAttribute('style');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,30 +1,24 @@
|
||||||
import { shallow } from 'enzyme';
|
import { render, screen } from '@testing-library/react';
|
||||||
import { Card, CardBody, CardHeader } from 'reactstrap';
|
|
||||||
import { SimpleCard } from '../../src/utils/SimpleCard';
|
import { SimpleCard } from '../../src/utils/SimpleCard';
|
||||||
|
|
||||||
describe('<SimpleCard />', () => {
|
describe('<SimpleCard />', () => {
|
||||||
it.each([
|
it('does not render title if not provided', () => {
|
||||||
[{}, 0],
|
render(<SimpleCard />);
|
||||||
[{ title: 'Cool title' }, 1],
|
expect(screen.queryByRole('heading')).not.toBeInTheDocument();
|
||||||
])('renders header only if title is provided', (props, expectedAmountOfHeaders) => {
|
});
|
||||||
const wrapper = shallow(<SimpleCard {...props} />);
|
|
||||||
|
|
||||||
expect(wrapper.find(CardHeader)).toHaveLength(expectedAmountOfHeaders);
|
it('renders provided title', () => {
|
||||||
|
render(<SimpleCard title="Cool title" />);
|
||||||
|
expect(screen.getByRole('heading')).toHaveTextContent('Cool title');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders children inside body', () => {
|
it('renders children inside body', () => {
|
||||||
const wrapper = shallow(<SimpleCard>Hello world</SimpleCard>);
|
render(<SimpleCard>Hello world</SimpleCard>);
|
||||||
const body = wrapper.find(CardBody);
|
expect(screen.getByText('Hello world')).toBeInTheDocument();
|
||||||
|
|
||||||
expect(body).toHaveLength(1);
|
|
||||||
expect(body.html()).toContain('Hello world');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes extra props to nested card', () => {
|
it.each(['primary', 'danger', 'warning'])('passes extra props to nested card', (color) => {
|
||||||
const wrapper = shallow(<SimpleCard className="foo" color="primary">Hello world</SimpleCard>);
|
const { container } = render(<SimpleCard className="foo" color={color}>Hello world</SimpleCard>);
|
||||||
const card = wrapper.find(Card);
|
expect(container.firstChild).toHaveAttribute('class', `foo card bg-${color}`);
|
||||||
|
|
||||||
expect(card.prop('className')).toEqual('foo');
|
|
||||||
expect(card.prop('color')).toEqual('primary');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { shallow } from 'enzyme';
|
import { fireEvent, render, screen } from '@testing-library/react';
|
||||||
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
|
import { formatISO } from 'date-fns';
|
||||||
import { NonOrphanVisits as createNonOrphanVisits } from '../../src/visits/NonOrphanVisits';
|
import { NonOrphanVisits as createNonOrphanVisits } from '../../src/visits/NonOrphanVisits';
|
||||||
import { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
|
import { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
|
||||||
import { VisitsInfo } from '../../src/visits/types';
|
import { Visit, VisitsInfo } from '../../src/visits/types';
|
||||||
import VisitsStats from '../../src/visits/VisitsStats';
|
|
||||||
import { Settings } from '../../src/settings/reducers/settings';
|
import { Settings } from '../../src/settings/reducers/settings';
|
||||||
import { ReportExporter } from '../../src/common/services/ReportExporter';
|
import { ReportExporter } from '../../src/common/services/ReportExporter';
|
||||||
import { SelectedServer } from '../../src/servers/data';
|
import { SelectedServer } from '../../src/servers/data';
|
||||||
import VisitsHeader from '../../src/visits/VisitsHeader';
|
|
||||||
|
|
||||||
jest.mock('react-router-dom', () => ({
|
jest.mock('react-router-dom', () => ({
|
||||||
...jest.requireActual('react-router-dom'),
|
...jest.requireActual('react-router-dom'),
|
||||||
|
@ -16,31 +16,37 @@ jest.mock('react-router-dom', () => ({
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('<NonOrphanVisits />', () => {
|
describe('<NonOrphanVisits />', () => {
|
||||||
it('wraps visits stats and header', () => {
|
const exportVisits = jest.fn();
|
||||||
const getNonOrphanVisits = jest.fn();
|
const getNonOrphanVisits = jest.fn();
|
||||||
const cancelGetNonOrphanVisits = jest.fn();
|
const cancelGetNonOrphanVisits = jest.fn();
|
||||||
const nonOrphanVisits = Mock.all<VisitsInfo>();
|
const nonOrphanVisits = Mock.of<VisitsInfo>({ visits: [Mock.of<Visit>({ date: formatISO(new Date()) })] });
|
||||||
const NonOrphanVisits = createNonOrphanVisits(Mock.all<ReportExporter>());
|
const NonOrphanVisits = createNonOrphanVisits(Mock.of<ReportExporter>({ exportVisits }));
|
||||||
|
|
||||||
const wrapper = shallow(
|
beforeEach(() => render(
|
||||||
|
<MemoryRouter>
|
||||||
<NonOrphanVisits
|
<NonOrphanVisits
|
||||||
{...Mock.of<MercureBoundProps>({ mercureInfo: {} })}
|
{...Mock.of<MercureBoundProps>({ mercureInfo: {} })}
|
||||||
getNonOrphanVisits={getNonOrphanVisits}
|
getNonOrphanVisits={getNonOrphanVisits}
|
||||||
nonOrphanVisits={nonOrphanVisits}
|
|
||||||
cancelGetNonOrphanVisits={cancelGetNonOrphanVisits}
|
cancelGetNonOrphanVisits={cancelGetNonOrphanVisits}
|
||||||
|
nonOrphanVisits={nonOrphanVisits}
|
||||||
settings={Mock.all<Settings>()}
|
settings={Mock.all<Settings>()}
|
||||||
selectedServer={Mock.all<SelectedServer>()}
|
selectedServer={Mock.all<SelectedServer>()}
|
||||||
/>,
|
/>
|
||||||
).dive();
|
</MemoryRouter>,
|
||||||
const stats = wrapper.find(VisitsStats);
|
));
|
||||||
const header = wrapper.find(VisitsHeader);
|
|
||||||
|
|
||||||
expect(stats).toHaveLength(1);
|
it('wraps visits stats and header', () => {
|
||||||
expect(header).toHaveLength(1);
|
expect(screen.getByRole('heading', { name: 'Non-orphan visits' })).toBeInTheDocument();
|
||||||
expect(stats.prop('cancelGetVisits')).toEqual(cancelGetNonOrphanVisits);
|
expect(getNonOrphanVisits).toHaveBeenCalled();
|
||||||
expect(stats.prop('visitsInfo')).toEqual(nonOrphanVisits);
|
});
|
||||||
expect(stats.prop('isOrphanVisits')).not.toBeDefined();
|
|
||||||
expect(header.prop('visits')).toEqual(nonOrphanVisits.visits);
|
it('exports visits when clicking the button', () => {
|
||||||
expect(header.prop('goBack')).toEqual(expect.any(Function));
|
const btn = screen.getByRole('button', { name: 'Export (1)' });
|
||||||
|
|
||||||
|
expect(exportVisits).not.toHaveBeenCalled();
|
||||||
|
expect(btn).toBeInTheDocument();
|
||||||
|
|
||||||
|
fireEvent.click(btn);
|
||||||
|
expect(exportVisits).toHaveBeenCalledWith('non_orphan_visits.csv', expect.anything());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue