mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2025-01-10 18:27:25 +03:00
Merge pull request #659 from acelaya-forks/feature/moar-rtl
Feature/moar rtl
This commit is contained in:
commit
807c5c3fb4
10 changed files with 287 additions and 222 deletions
|
@ -26,7 +26,7 @@ export const DeleteServerModal: FC<DeleteServerModalConnectProps> = (
|
|||
|
||||
return (
|
||||
<Modal isOpen={isOpen} toggle={toggle} centered>
|
||||
<ModalHeader toggle={toggle}><span className="text-danger">Remove server</span></ModalHeader>
|
||||
<ModalHeader toggle={toggle} className="text-danger">Remove server</ModalHeader>
|
||||
<ModalBody>
|
||||
<p>Are you sure you want to remove <b>{server ? server.name : ''}</b>?</p>
|
||||
<p>
|
||||
|
|
|
@ -39,7 +39,7 @@ export const ManageServersRowDropdown = (
|
|||
<DropdownItem tag={Link} to={`${serverUrl}/edit`}>
|
||||
<FontAwesomeIcon icon={editIcon} fixedWidth /> Edit server
|
||||
</DropdownItem>
|
||||
<DropdownItem onClick={() => setAutoConnect(server, !server.autoConnect)}>
|
||||
<DropdownItem onClick={() => setAutoConnect(server, !isAutoConnect)}>
|
||||
<FontAwesomeIcon icon={autoConnectIcon} fixedWidth /> {isAutoConnect ? 'Do not a' : 'A'}uto-connect
|
||||
</DropdownItem>
|
||||
<DropdownItem divider />
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import { parseISO, format as formatDate, getUnixTime, formatDistance } from 'date-fns';
|
||||
import { isDateObject } from './helpers/date';
|
||||
|
||||
export interface DateProps {
|
||||
export interface TimeProps {
|
||||
date: Date | string;
|
||||
format?: string;
|
||||
relative?: boolean;
|
||||
}
|
||||
|
||||
export const Time = ({ date, format = 'yyyy-MM-dd HH:mm', relative = false }: DateProps) => {
|
||||
export const Time = ({ date, format = 'yyyy-MM-dd HH:mm', relative = false }: TimeProps) => {
|
||||
const dateObject = isDateObject(date) ? date : parseISO(date);
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { shallow, ShallowWrapper } from 'enzyme';
|
||||
import { Button, Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { Mock } from 'ts-mockery';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { DeleteServerModal } from '../../src/servers/DeleteServerModal';
|
||||
|
@ -8,56 +8,63 @@ import { ServerWithId } from '../../src/servers/data';
|
|||
jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useNavigate: jest.fn() }));
|
||||
|
||||
describe('<DeleteServerModal />', () => {
|
||||
let wrapper: ShallowWrapper;
|
||||
const deleteServerMock = jest.fn();
|
||||
const navigate = jest.fn();
|
||||
const toggleMock = jest.fn();
|
||||
const serverName = 'the_server_name';
|
||||
|
||||
beforeEach(() => {
|
||||
const setUp = () => {
|
||||
(useNavigate as any).mockReturnValue(navigate);
|
||||
|
||||
wrapper = shallow(
|
||||
<DeleteServerModal
|
||||
server={Mock.of<ServerWithId>({ name: serverName })}
|
||||
toggle={toggleMock}
|
||||
isOpen
|
||||
deleteServer={deleteServerMock}
|
||||
/>,
|
||||
);
|
||||
});
|
||||
afterEach(() => wrapper.unmount());
|
||||
return {
|
||||
user: userEvent.setup(),
|
||||
...render(
|
||||
<DeleteServerModal
|
||||
server={Mock.of<ServerWithId>({ name: serverName })}
|
||||
toggle={toggleMock}
|
||||
isOpen
|
||||
deleteServer={deleteServerMock}
|
||||
/>,
|
||||
),
|
||||
};
|
||||
};
|
||||
|
||||
afterEach(jest.clearAllMocks);
|
||||
|
||||
it('renders a modal window', () => {
|
||||
expect(wrapper.find(Modal)).toHaveLength(1);
|
||||
expect(wrapper.find(ModalHeader)).toHaveLength(1);
|
||||
expect(wrapper.find(ModalBody)).toHaveLength(1);
|
||||
expect(wrapper.find(ModalFooter)).toHaveLength(1);
|
||||
setUp();
|
||||
|
||||
expect(screen.getByRole('dialog')).toBeInTheDocument();
|
||||
expect(screen.getByRole('heading')).toHaveTextContent('Remove server');
|
||||
});
|
||||
|
||||
it('displays the name of the server as part of the content', () => {
|
||||
const modalBody = wrapper.find(ModalBody);
|
||||
setUp();
|
||||
|
||||
expect(modalBody.find('p').first().text()).toEqual(
|
||||
`Are you sure you want to remove ${serverName}?`,
|
||||
);
|
||||
expect(screen.getByText(/^Are you sure you want to remove/)).toBeInTheDocument();
|
||||
expect(screen.getByText(serverName)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('toggles when clicking cancel button', () => {
|
||||
const cancelBtn = wrapper.find(Button).first();
|
||||
it.each([
|
||||
[() => screen.getByRole('button', { name: 'Cancel' })],
|
||||
[() => screen.getByLabelText('Close')],
|
||||
])('toggles when clicking cancel button', async (getButton) => {
|
||||
const { user } = setUp();
|
||||
|
||||
cancelBtn.simulate('click');
|
||||
expect(toggleMock).not.toHaveBeenCalled();
|
||||
await user.click(getButton());
|
||||
|
||||
expect(toggleMock).toHaveBeenCalledTimes(1);
|
||||
expect(deleteServerMock).not.toHaveBeenCalled();
|
||||
expect(navigate).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('deletes server when clicking accept button', () => {
|
||||
const acceptBtn = wrapper.find(Button).last();
|
||||
it('deletes server when clicking accept button', async () => {
|
||||
const { user } = setUp();
|
||||
|
||||
acceptBtn.simulate('click');
|
||||
expect(toggleMock).not.toHaveBeenCalled();
|
||||
expect(deleteServerMock).not.toHaveBeenCalled();
|
||||
expect(navigate).not.toHaveBeenCalled();
|
||||
await user.click(screen.getByRole('button', { name: 'Delete' }));
|
||||
|
||||
expect(toggleMock).toHaveBeenCalledTimes(1);
|
||||
expect(deleteServerMock).toHaveBeenCalledTimes(1);
|
||||
|
|
|
@ -1,93 +1,103 @@
|
|||
import { Mock } from 'ts-mockery';
|
||||
import { shallow, ShallowWrapper } from 'enzyme';
|
||||
import { Button } from 'reactstrap';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { render, screen, waitFor } from '@testing-library/react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import ServersExporter from '../../src/servers/services/ServersExporter';
|
||||
import { ManageServers as createManageServers } from '../../src/servers/ManageServers';
|
||||
import { ServersMap, ServerWithId } from '../../src/servers/data';
|
||||
import { SearchField } from '../../src/utils/SearchField';
|
||||
import { Result } from '../../src/utils/Result';
|
||||
|
||||
describe('<ManageServers />', () => {
|
||||
const exportServers = jest.fn();
|
||||
const serversExporter = Mock.of<ServersExporter>({ exportServers });
|
||||
const ImportServersBtn = () => null;
|
||||
const ManageServersRow = () => null;
|
||||
const useTimeoutToggle = jest.fn().mockReturnValue([false, jest.fn()]);
|
||||
const ManageServers = createManageServers(serversExporter, ImportServersBtn, useTimeoutToggle, ManageServersRow);
|
||||
let wrapper: ShallowWrapper;
|
||||
const ManageServers = createManageServers(
|
||||
serversExporter,
|
||||
() => <span>ImportServersBtn</span>,
|
||||
useTimeoutToggle,
|
||||
({ hasAutoConnect }) => <span>ManageServersRow {hasAutoConnect ? '[YES]' : '[NO]'}</span>,
|
||||
);
|
||||
const createServerMock = (value: string, autoConnect = false) => Mock.of<ServerWithId>(
|
||||
{ id: value, name: value, url: value, autoConnect },
|
||||
);
|
||||
const createWrapper = (servers: ServersMap = {}) => {
|
||||
wrapper = shallow(<ManageServers servers={servers} />);
|
||||
|
||||
return wrapper;
|
||||
};
|
||||
const setUp = (servers: ServersMap = {}) => ({
|
||||
user: userEvent.setup(),
|
||||
...render(<MemoryRouter><ManageServers servers={servers} /></MemoryRouter>),
|
||||
});
|
||||
|
||||
afterEach(jest.clearAllMocks);
|
||||
afterEach(() => wrapper?.unmount());
|
||||
|
||||
it('shows search field which allows searching servers, affecting te amount of rendered rows', () => {
|
||||
const wrapper = createWrapper({
|
||||
it('shows search field which allows searching servers, affecting te amount of rendered rows', async () => {
|
||||
const { user } = setUp({
|
||||
foo: createServerMock('foo'),
|
||||
bar: createServerMock('bar'),
|
||||
baz: createServerMock('baz'),
|
||||
});
|
||||
const searchField = wrapper.find(SearchField);
|
||||
const search = async (searchTerm: string) => {
|
||||
await user.clear(screen.getByPlaceholderText('Search...'));
|
||||
await user.type(screen.getByPlaceholderText('Search...'), searchTerm);
|
||||
};
|
||||
|
||||
expect(wrapper.find(ManageServersRow)).toHaveLength(3);
|
||||
expect(wrapper.find('tbody').find('tr')).toHaveLength(0);
|
||||
expect(screen.getAllByText(/^ManageServersRow/)).toHaveLength(3);
|
||||
expect(screen.queryByText('No servers found.')).not.toBeInTheDocument();
|
||||
|
||||
searchField.simulate('change', 'foo');
|
||||
expect(wrapper.find(ManageServersRow)).toHaveLength(1);
|
||||
expect(wrapper.find('tbody').find('tr')).toHaveLength(0);
|
||||
await search('foo');
|
||||
await waitFor(() => expect(screen.getAllByText(/^ManageServersRow/)).toHaveLength(1));
|
||||
expect(screen.queryByText('No servers found.')).not.toBeInTheDocument();
|
||||
|
||||
searchField.simulate('change', 'ba');
|
||||
expect(wrapper.find(ManageServersRow)).toHaveLength(2);
|
||||
expect(wrapper.find('tbody').find('tr')).toHaveLength(0);
|
||||
await search('ba');
|
||||
await waitFor(() => expect(screen.getAllByText(/^ManageServersRow/)).toHaveLength(2));
|
||||
expect(screen.queryByText('No servers found.')).not.toBeInTheDocument();
|
||||
|
||||
searchField.simulate('change', 'invalid');
|
||||
expect(wrapper.find(ManageServersRow)).toHaveLength(0);
|
||||
expect(wrapper.find('tbody').find('tr')).toHaveLength(1);
|
||||
await search('invalid');
|
||||
await waitFor(() => expect(screen.queryByText(/^ManageServersRow/)).not.toBeInTheDocument());
|
||||
expect(screen.getByText('No servers found.')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it.each([
|
||||
[createServerMock('foo'), 3],
|
||||
[createServerMock('foo', true), 4],
|
||||
])('shows different amount of columns if there are at least one auto-connect server', (server, expectedCols) => {
|
||||
const wrapper = createWrapper({ server });
|
||||
const row = wrapper.find(ManageServersRow);
|
||||
setUp({ server });
|
||||
|
||||
expect(wrapper.find('th')).toHaveLength(expectedCols);
|
||||
expect(row.prop('hasAutoConnect')).toEqual(server.autoConnect);
|
||||
expect(screen.getAllByRole('columnheader')).toHaveLength(expectedCols);
|
||||
if (server.autoConnect) {
|
||||
expect(screen.getByText(/\[YES\]/)).toBeInTheDocument();
|
||||
expect(screen.queryByText(/\[NO\]/)).not.toBeInTheDocument();
|
||||
} else {
|
||||
expect(screen.queryByText(/\[YES\]/)).not.toBeInTheDocument();
|
||||
expect(screen.getByText(/\[NO\]/)).toBeInTheDocument();
|
||||
}
|
||||
});
|
||||
|
||||
it.each([
|
||||
[{}, 1],
|
||||
[{ foo: createServerMock('foo') }, 2],
|
||||
[{}, 0],
|
||||
[{ foo: createServerMock('foo') }, 1],
|
||||
])('shows export button if the list of servers is not empty', (servers, expectedButtons) => {
|
||||
const wrapper = createWrapper(servers);
|
||||
const exportBtn = wrapper.find(Button);
|
||||
|
||||
expect(exportBtn).toHaveLength(expectedButtons);
|
||||
setUp(servers);
|
||||
expect(screen.queryAllByRole('button', { name: 'Export servers' })).toHaveLength(expectedButtons);
|
||||
});
|
||||
|
||||
it('allows exporting servers when clicking on button', () => {
|
||||
const wrapper = createWrapper({ foo: createServerMock('foo') });
|
||||
const exportBtn = wrapper.find(Button).first();
|
||||
it('allows exporting servers when clicking on button', async () => {
|
||||
const { user } = setUp({ foo: createServerMock('foo') });
|
||||
|
||||
expect(exportServers).not.toHaveBeenCalled();
|
||||
exportBtn.simulate('click');
|
||||
await user.click(screen.getByRole('button', { name: 'Export servers' }));
|
||||
expect(exportServers).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('shows an error message if an error occurs while importing servers', () => {
|
||||
useTimeoutToggle.mockReturnValue([true, jest.fn()]);
|
||||
it.each([[true], [false]])('shows an error message if an error occurs while importing servers', (hasError) => {
|
||||
useTimeoutToggle.mockReturnValue([hasError, jest.fn()]);
|
||||
|
||||
const wrapper = createWrapper({ foo: createServerMock('foo') });
|
||||
const result = wrapper.find(Result);
|
||||
setUp({ foo: createServerMock('foo') });
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result.prop('type')).toEqual('error');
|
||||
if (hasError) {
|
||||
expect(
|
||||
screen.getByText('The servers could not be imported. Make sure the format is correct.'),
|
||||
).toBeInTheDocument();
|
||||
} else {
|
||||
expect(
|
||||
screen.queryByText('The servers could not be imported. Make sure the format is correct.'),
|
||||
).not.toBeInTheDocument();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,66 +1,58 @@
|
|||
import { shallow, ShallowWrapper } from 'enzyme';
|
||||
import { UncontrolledTooltip } from 'reactstrap';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { ManageServersRow as createManageServersRow } from '../../src/servers/ManageServersRow';
|
||||
import { ServerWithId } from '../../src/servers/data';
|
||||
|
||||
describe('<ManageServersRow />', () => {
|
||||
const ManageServersRowDropdown = () => null;
|
||||
const ManageServersRow = createManageServersRow(ManageServersRowDropdown);
|
||||
const ManageServersRow = createManageServersRow(() => <span>ManageServersRowDropdown</span>);
|
||||
const server: ServerWithId = {
|
||||
name: 'My server',
|
||||
url: 'https://example.com',
|
||||
apiKey: '123',
|
||||
id: 'abc',
|
||||
};
|
||||
let wrapper: ShallowWrapper;
|
||||
const createWrapper = (hasAutoConnect = false, autoConnect = false) => {
|
||||
wrapper = shallow(<ManageServersRow server={{ ...server, autoConnect }} hasAutoConnect={hasAutoConnect} />);
|
||||
|
||||
return wrapper;
|
||||
};
|
||||
|
||||
afterEach(() => wrapper?.unmount());
|
||||
const setUp = (hasAutoConnect = false, autoConnect = false) => render(
|
||||
<MemoryRouter>
|
||||
<table>
|
||||
<tbody>
|
||||
<ManageServersRow server={{ ...server, autoConnect }} hasAutoConnect={hasAutoConnect} />
|
||||
</tbody>
|
||||
</table>
|
||||
</MemoryRouter>,
|
||||
);
|
||||
|
||||
it.each([
|
||||
[true, 4],
|
||||
[false, 3],
|
||||
])('renders expected amount of columns', (hasAutoConnect, expectedCols) => {
|
||||
const wrapper = createWrapper(hasAutoConnect);
|
||||
const td = wrapper.find('td');
|
||||
const th = wrapper.find('th');
|
||||
setUp(hasAutoConnect);
|
||||
|
||||
const td = screen.getAllByRole('cell');
|
||||
const th = screen.getAllByRole('columnheader');
|
||||
|
||||
expect(td.length + th.length).toEqual(expectedCols);
|
||||
});
|
||||
|
||||
it('renders a dropdown', () => {
|
||||
const wrapper = createWrapper();
|
||||
const dropdown = wrapper.find(ManageServersRowDropdown);
|
||||
|
||||
expect(dropdown).toHaveLength(1);
|
||||
expect(dropdown.prop('server')).toEqual(expect.objectContaining(server));
|
||||
setUp();
|
||||
expect(screen.getByText('ManageServersRowDropdown')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it.each([
|
||||
[true, 1],
|
||||
[false, 0],
|
||||
])('renders auto-connect icon only if server is autoConnect', (autoConnect, expectedIcons) => {
|
||||
const wrapper = createWrapper(true, autoConnect);
|
||||
const icon = wrapper.find(FontAwesomeIcon);
|
||||
const iconTooltip = wrapper.find(UncontrolledTooltip);
|
||||
|
||||
expect(icon).toHaveLength(expectedIcons);
|
||||
expect(iconTooltip).toHaveLength(expectedIcons);
|
||||
[true],
|
||||
[false],
|
||||
])('renders auto-connect icon only if server is autoConnect', (autoConnect) => {
|
||||
const { container } = setUp(true, autoConnect);
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders server props where appropriate', () => {
|
||||
const wrapper = createWrapper();
|
||||
const link = wrapper.find(Link);
|
||||
const td = wrapper.find('td').first();
|
||||
setUp();
|
||||
|
||||
expect(link.prop('to')).toEqual(`/server/${server.id}`);
|
||||
expect(link.prop('children')).toEqual(server.name);
|
||||
expect(td.prop('children')).toEqual(server.url);
|
||||
const link = screen.getByRole('link');
|
||||
|
||||
expect(link).toHaveAttribute('href', `/server/${server.id}`);
|
||||
expect(link).toHaveTextContent(server.name);
|
||||
expect(screen.getByText(server.url)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,84 +1,60 @@
|
|||
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 { DropdownItem } from 'reactstrap';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { ServerWithId } from '../../src/servers/data';
|
||||
import { ManageServersRowDropdown as createManageServersRowDropdown } from '../../src/servers/ManageServersRowDropdown';
|
||||
|
||||
describe('<ManageServersRowDropdown />', () => {
|
||||
const DeleteServerModal = () => null;
|
||||
const ManageServersRowDropdown = createManageServersRowDropdown(DeleteServerModal);
|
||||
const ManageServersRowDropdown = createManageServersRowDropdown(
|
||||
({ isOpen }) => <span>DeleteServerModal {isOpen ? '[OPEN]' : '[CLOSED]'}</span>,
|
||||
);
|
||||
const setAutoConnect = jest.fn();
|
||||
let wrapper: ShallowWrapper;
|
||||
const createWrapper = (autoConnect = false) => {
|
||||
const setUp = (autoConnect = false) => {
|
||||
const server = Mock.of<ServerWithId>({ id: 'abc123', autoConnect });
|
||||
|
||||
wrapper = shallow(<ManageServersRowDropdown setAutoConnect={setAutoConnect} server={server} />);
|
||||
|
||||
return wrapper;
|
||||
return {
|
||||
user: userEvent.setup(),
|
||||
...render(
|
||||
<MemoryRouter>
|
||||
<ManageServersRowDropdown setAutoConnect={setAutoConnect} server={server} />
|
||||
</MemoryRouter>,
|
||||
),
|
||||
};
|
||||
};
|
||||
|
||||
afterEach(jest.clearAllMocks);
|
||||
|
||||
it('renders expected amount of dropdown items', () => {
|
||||
const wrapper = createWrapper();
|
||||
const items = wrapper.find(DropdownItem);
|
||||
it('renders expected amount of dropdown items', async () => {
|
||||
const { user } = setUp();
|
||||
|
||||
expect(items).toHaveLength(5);
|
||||
expect(items.find('[divider]')).toHaveLength(1);
|
||||
expect(items.at(0).prop('to')).toEqual('/server/abc123');
|
||||
expect(items.at(1).prop('to')).toEqual('/server/abc123/edit');
|
||||
expect(screen.queryByRole('menu')).not.toBeInTheDocument();
|
||||
await user.click(screen.getByRole('button'));
|
||||
expect(screen.getByRole('menu')).toBeInTheDocument();
|
||||
|
||||
expect(screen.getAllByRole('menuitem')).toHaveLength(4);
|
||||
expect(screen.getByRole('menuitem', { name: 'Connect' })).toHaveAttribute('href', '/server/abc123');
|
||||
expect(screen.getByRole('menuitem', { name: 'Edit server' })).toHaveAttribute('href', '/server/abc123/edit');
|
||||
});
|
||||
|
||||
it('allows toggling auto-connect', () => {
|
||||
const wrapper = createWrapper();
|
||||
it('allows toggling auto-connect', async () => {
|
||||
const { user } = setUp();
|
||||
|
||||
expect(setAutoConnect).not.toHaveBeenCalled();
|
||||
wrapper.find(DropdownItem).at(2).simulate('click');
|
||||
await user.click(screen.getByRole('button'));
|
||||
await user.click(screen.getByRole('menuitem', { name: 'Auto-connect' }));
|
||||
expect(setAutoConnect).toHaveBeenCalledWith(expect.objectContaining({ id: 'abc123' }), true);
|
||||
});
|
||||
|
||||
it('renders a modal', () => {
|
||||
const wrapper = createWrapper();
|
||||
const modal = wrapper.find(DeleteServerModal);
|
||||
it('renders deletion modal', async () => {
|
||||
const { user } = setUp();
|
||||
|
||||
expect(modal).toHaveLength(1);
|
||||
expect(modal.prop('redirectHome')).toEqual(false);
|
||||
expect(modal.prop('server')).toEqual(expect.objectContaining({ id: 'abc123' }));
|
||||
expect(modal.prop('isOpen')).toEqual(false);
|
||||
});
|
||||
expect(screen.queryByText('DeleteServerModal [OPEN]')).not.toBeInTheDocument();
|
||||
expect(screen.getByText('DeleteServerModal [CLOSED]')).toBeInTheDocument();
|
||||
|
||||
it('allows toggling the modal', () => {
|
||||
const wrapper = createWrapper();
|
||||
const modalToggle = wrapper.find(DropdownItem).last();
|
||||
await user.click(screen.getByRole('button'));
|
||||
await user.click(screen.getByRole('menuitem', { name: 'Remove server' }));
|
||||
|
||||
expect(wrapper.find(DeleteServerModal).prop('isOpen')).toEqual(false);
|
||||
|
||||
modalToggle.simulate('click');
|
||||
expect(wrapper.find(DeleteServerModal).prop('isOpen')).toEqual(true);
|
||||
|
||||
(wrapper.find(DeleteServerModal).prop('toggle') as Function)();
|
||||
expect(wrapper.find(DeleteServerModal).prop('isOpen')).toEqual(false);
|
||||
});
|
||||
|
||||
it('can be toggled', () => {
|
||||
const wrapper = createWrapper();
|
||||
|
||||
expect(wrapper.prop('isOpen')).toEqual(false);
|
||||
|
||||
(wrapper.prop('toggle') as Function)();
|
||||
expect(wrapper.prop('isOpen')).toEqual(true);
|
||||
|
||||
(wrapper.prop('toggle') as Function)();
|
||||
expect(wrapper.prop('isOpen')).toEqual(false);
|
||||
});
|
||||
|
||||
it.each([
|
||||
[true, 'Do not auto-connect'],
|
||||
[false, 'Auto-connect'],
|
||||
])('shows different auto-connect toggle text depending on current server status', (autoConnect, expectedText) => {
|
||||
const wrapper = createWrapper(autoConnect);
|
||||
const item = wrapper.find(DropdownItem).at(2);
|
||||
|
||||
expect(item.html()).toContain(expectedText);
|
||||
expect(screen.getByText('DeleteServerModal [OPEN]')).toBeInTheDocument();
|
||||
expect(screen.queryByText('DeleteServerModal [CLOSED]')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { shallow, ShallowWrapper } from 'enzyme';
|
||||
import { ListGroup } from 'reactstrap';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { Mock } from 'ts-mockery';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { ServersListGroup } from '../../src/servers/ServersListGroup';
|
||||
import { ServerWithId } from '../../src/servers/data';
|
||||
|
||||
|
@ -9,44 +9,36 @@ describe('<ServersListGroup />', () => {
|
|||
Mock.of<ServerWithId>({ name: 'foo', id: '123' }),
|
||||
Mock.of<ServerWithId>({ name: 'bar', id: '456' }),
|
||||
];
|
||||
let wrapped: ShallowWrapper;
|
||||
const createComponent = (params: { servers?: ServerWithId[]; withChildren?: boolean; embedded?: boolean }) => {
|
||||
const setUp = (params: { servers?: ServerWithId[]; withChildren?: boolean; embedded?: boolean }) => {
|
||||
const { servers = [], withChildren = true, embedded } = params;
|
||||
|
||||
wrapped = shallow(
|
||||
<ServersListGroup servers={servers} embedded={embedded}>
|
||||
{withChildren ? 'The list of servers' : undefined}
|
||||
</ServersListGroup>,
|
||||
return render(
|
||||
<MemoryRouter>
|
||||
<ServersListGroup servers={servers} embedded={embedded}>
|
||||
{withChildren ? 'The list of servers' : undefined}
|
||||
</ServersListGroup>
|
||||
</MemoryRouter>,
|
||||
);
|
||||
|
||||
return wrapped;
|
||||
};
|
||||
|
||||
afterEach(() => wrapped?.unmount());
|
||||
|
||||
it('renders title', () => {
|
||||
const wrapped = createComponent({});
|
||||
const title = wrapped.find('h5');
|
||||
|
||||
expect(title).toHaveLength(1);
|
||||
expect(title.text()).toEqual('The list of servers');
|
||||
setUp({});
|
||||
expect(screen.getByRole('heading')).toHaveTextContent('The list of servers');
|
||||
});
|
||||
|
||||
it('does not render title when children is not provided', () => {
|
||||
const wrapped = createComponent({ withChildren: false });
|
||||
const title = wrapped.find('h5');
|
||||
|
||||
expect(title).toHaveLength(0);
|
||||
setUp({ withChildren: false });
|
||||
expect(screen.queryByRole('heading')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it.each([
|
||||
[servers],
|
||||
[[]],
|
||||
])('shows servers list', (servers) => {
|
||||
const wrapped = createComponent({ servers });
|
||||
setUp({ servers });
|
||||
|
||||
expect(wrapped.find(ListGroup)).toHaveLength(servers.length ? 1 : 0);
|
||||
expect(wrapped.find('ServerListItem')).toHaveLength(servers.length);
|
||||
expect(screen.queryAllByRole('list')).toHaveLength(servers.length ? 1 : 0);
|
||||
expect(screen.queryAllByRole('link')).toHaveLength(servers.length);
|
||||
});
|
||||
|
||||
it.each([
|
||||
|
@ -54,9 +46,7 @@ describe('<ServersListGroup />', () => {
|
|||
[false, 'servers-list__list-group'],
|
||||
[undefined, 'servers-list__list-group'],
|
||||
])('renders proper classes for embedded', (embedded, expectedClasses) => {
|
||||
const wrapped = createComponent({ servers, embedded });
|
||||
const listGroup = wrapped.find(ListGroup);
|
||||
|
||||
expect(listGroup.prop('className')).toEqual(expectedClasses);
|
||||
setUp({ servers, embedded });
|
||||
expect(screen.getByRole('list')).toHaveAttribute('class', `${expectedClasses} list-group`);
|
||||
});
|
||||
});
|
||||
|
|
98
test/servers/__snapshots__/ManageServersRow.test.tsx.snap
Normal file
98
test/servers/__snapshots__/ManageServersRow.test.tsx.snap
Normal file
|
@ -0,0 +1,98 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<ManageServersRow /> renders auto-connect icon only if server is autoConnect 1`] = `
|
||||
<div>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr
|
||||
class="responsive-table__row"
|
||||
>
|
||||
<td
|
||||
class="responsive-table__cell"
|
||||
data-th="Auto-connect"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="svg-inline--fa fa-check text-primary"
|
||||
data-icon="check"
|
||||
data-prefix="fas"
|
||||
focusable="false"
|
||||
id="autoConnectIcon"
|
||||
role="img"
|
||||
viewBox="0 0 448 512"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M438.6 105.4C451.1 117.9 451.1 138.1 438.6 150.6L182.6 406.6C170.1 419.1 149.9 419.1 137.4 406.6L9.372 278.6C-3.124 266.1-3.124 245.9 9.372 233.4C21.87 220.9 42.13 220.9 54.63 233.4L159.1 338.7L393.4 105.4C405.9 92.88 426.1 92.88 438.6 105.4H438.6z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</td>
|
||||
<th
|
||||
class="responsive-table__cell"
|
||||
data-th="Name"
|
||||
>
|
||||
<a
|
||||
href="/server/abc"
|
||||
>
|
||||
My server
|
||||
</a>
|
||||
</th>
|
||||
<td
|
||||
class="responsive-table__cell"
|
||||
data-th="Base URL"
|
||||
>
|
||||
https://example.com
|
||||
</td>
|
||||
<td
|
||||
class="responsive-table__cell text-end"
|
||||
>
|
||||
<span>
|
||||
ManageServersRowDropdown
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`<ManageServersRow /> renders auto-connect icon only if server is autoConnect 2`] = `
|
||||
<div>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr
|
||||
class="responsive-table__row"
|
||||
>
|
||||
<td
|
||||
class="responsive-table__cell"
|
||||
data-th="Auto-connect"
|
||||
/>
|
||||
<th
|
||||
class="responsive-table__cell"
|
||||
data-th="Name"
|
||||
>
|
||||
<a
|
||||
href="/server/abc"
|
||||
>
|
||||
My server
|
||||
</a>
|
||||
</th>
|
||||
<td
|
||||
class="responsive-table__cell"
|
||||
data-th="Base URL"
|
||||
>
|
||||
https://example.com
|
||||
</td>
|
||||
<td
|
||||
class="responsive-table__cell text-end"
|
||||
>
|
||||
<span>
|
||||
ManageServersRowDropdown
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
`;
|
|
@ -1,30 +1,22 @@
|
|||
import { shallow, ShallowWrapper } from 'enzyme';
|
||||
import { DateProps, Time } from '../../src/utils/Time';
|
||||
import { render } from '@testing-library/react';
|
||||
import { TimeProps, Time } from '../../src/utils/Time';
|
||||
import { parseDate } from '../../src/utils/helpers/date';
|
||||
|
||||
describe('<Time />', () => {
|
||||
let wrapper: ShallowWrapper;
|
||||
const createWrapper = (props: DateProps) => {
|
||||
wrapper = shallow(<Time {...props} />);
|
||||
|
||||
return wrapper;
|
||||
};
|
||||
|
||||
afterEach(() => wrapper?.unmount());
|
||||
const setUp = (props: TimeProps) => render(<Time {...props} />);
|
||||
|
||||
it.each([
|
||||
[{ date: parseDate('2020-05-05', 'yyyy-MM-dd') }, '1588636800000', '2020-05-05 00:00'],
|
||||
[{ date: parseDate('2021-03-20', 'yyyy-MM-dd'), format: 'dd/MM/yyyy' }, '1616198400000', '20/03/2021'],
|
||||
])('includes expected dateTime and format', (props, expectedDateTime, expectedFormatted) => {
|
||||
const wrapper = createWrapper(props);
|
||||
const { container } = setUp(props);
|
||||
|
||||
expect(wrapper.prop('dateTime')).toEqual(expectedDateTime);
|
||||
expect(wrapper.prop('children')).toEqual(expectedFormatted);
|
||||
expect(container.firstChild).toHaveAttribute('datetime', expectedDateTime);
|
||||
expect(container.firstChild).toHaveTextContent(expectedFormatted);
|
||||
});
|
||||
|
||||
it('renders relative times when requested', () => {
|
||||
const wrapper = createWrapper({ date: new Date(), relative: true });
|
||||
|
||||
expect(wrapper.prop('children')).toContain(' ago');
|
||||
const { container } = setUp({ date: new Date(), relative: true });
|
||||
expect(container.firstChild).toHaveTextContent(' ago');
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue