mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2026-03-11 10:03:51 +00:00
Move shlink-frontend-kit tests to its own dir
This commit is contained in:
@@ -2,10 +2,10 @@ import type { ReactNode } from 'react';
|
||||
import type { CardProps } from 'reactstrap';
|
||||
import { Card, CardBody, CardHeader } from 'reactstrap';
|
||||
|
||||
interface SimpleCardProps extends Omit<CardProps, 'title'> {
|
||||
export type SimpleCardProps = Omit<CardProps, 'title'> & {
|
||||
title?: ReactNode;
|
||||
bodyClassName?: string;
|
||||
}
|
||||
};
|
||||
|
||||
export const SimpleCard = ({ title, children, bodyClassName, ...rest }: SimpleCardProps) => (
|
||||
<Card {...rest}>
|
||||
|
||||
@@ -10,9 +10,9 @@ export type BooleanControlProps = PropsWithChildren<{
|
||||
inline?: boolean;
|
||||
}>;
|
||||
|
||||
interface BooleanControlWithTypeProps extends BooleanControlProps {
|
||||
type BooleanControlWithTypeProps = BooleanControlProps & {
|
||||
type: 'switch' | 'checkbox';
|
||||
}
|
||||
};
|
||||
|
||||
export const BooleanControl: FC<BooleanControlWithTypeProps> = (
|
||||
{ checked = false, onChange = identity, className, children, type, inline = false },
|
||||
|
||||
@@ -7,13 +7,13 @@ import './SearchField.scss';
|
||||
const DEFAULT_SEARCH_INTERVAL = 500;
|
||||
let timer: NodeJS.Timeout | null;
|
||||
|
||||
interface SearchFieldProps {
|
||||
type SearchFieldProps = {
|
||||
onChange: (value: string) => void;
|
||||
className?: string;
|
||||
large?: boolean;
|
||||
noBorder?: boolean;
|
||||
initialValue?: string;
|
||||
}
|
||||
};
|
||||
|
||||
export const SearchField = ({ onChange, className, large = true, noBorder = false, initialValue = '' }: SearchFieldProps) => {
|
||||
const [searchTerm, setSearchTerm] = useState(initialValue);
|
||||
|
||||
@@ -7,14 +7,14 @@ import type { Order, OrderDir } from './ordering';
|
||||
import { determineOrderDir } from './ordering';
|
||||
import './OrderingDropdown.scss';
|
||||
|
||||
export interface OrderingDropdownProps<T extends string = string> {
|
||||
export type OrderingDropdownProps<T extends string = string> = {
|
||||
items: Record<T, string>;
|
||||
order: Order<T>;
|
||||
onChange: (orderField?: T, orderDir?: OrderDir) => void;
|
||||
isButton?: boolean;
|
||||
right?: boolean;
|
||||
prefixed?: boolean;
|
||||
}
|
||||
};
|
||||
|
||||
export function OrderingDropdown<T extends string = string>(
|
||||
{ items, order, onChange, isButton = true, right = false, prefixed = true }: OrderingDropdownProps<T>,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
export type OrderDir = 'ASC' | 'DESC' | undefined;
|
||||
|
||||
export interface Order<Fields> {
|
||||
export type Order<Fields> = {
|
||||
field?: Fields;
|
||||
dir?: OrderDir;
|
||||
}
|
||||
};
|
||||
|
||||
export const determineOrderDir = <T extends string = string>(
|
||||
currentField: T,
|
||||
|
||||
8
shlink-frontend-kit/test/__helpers__/setUpTest.ts
Normal file
8
shlink-frontend-kit/test/__helpers__/setUpTest.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { render } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event/index';
|
||||
import type { ReactElement } from 'react';
|
||||
|
||||
export const renderWithEvents = (element: ReactElement) => ({
|
||||
user: userEvent.setup(),
|
||||
...render(element),
|
||||
});
|
||||
50
shlink-frontend-kit/test/block/Message.test.tsx
Normal file
50
shlink-frontend-kit/test/block/Message.test.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import type { MessageProps } from '../../src';
|
||||
import { Message } from '../../src';
|
||||
|
||||
describe('<Message />', () => {
|
||||
const setUp = (props: PropsWithChildren<MessageProps> = {}) => render(<Message {...props} />);
|
||||
|
||||
it.each([
|
||||
[true, 'col-md-12'],
|
||||
[false, 'col-md-10 offset-md-1'],
|
||||
[undefined, 'col-md-10 offset-md-1'],
|
||||
])('renders expected classes based on width', (fullWidth, expectedClass) => {
|
||||
const { container } = setUp({ fullWidth });
|
||||
expect(container.firstChild?.firstChild).toHaveClass(expectedClass);
|
||||
});
|
||||
|
||||
it.each([
|
||||
[true, 'These are the children contents'],
|
||||
[false, 'These are the children contents'],
|
||||
[true, undefined],
|
||||
[false, undefined],
|
||||
])('renders expected content', (loading, children) => {
|
||||
setUp({ loading, children });
|
||||
|
||||
expect(screen.queryAllByRole('img', { hidden: true })).toHaveLength(loading ? 1 : 0);
|
||||
|
||||
if (loading) {
|
||||
expect(screen.getByText(children || 'Loading...')).toHaveClass('ms-2');
|
||||
} else {
|
||||
expect(screen.getByRole('heading')).toHaveTextContent(children || '');
|
||||
}
|
||||
});
|
||||
|
||||
it.each([
|
||||
['error', 'border-danger', 'text-danger'],
|
||||
['default', '', 'text-muted'],
|
||||
[undefined, '', 'text-muted'],
|
||||
])('renders proper classes based on message type', (type, expectedCardClass, expectedH3Class) => {
|
||||
const { container } = setUp({ type: type as 'default' | 'error' | undefined });
|
||||
|
||||
expect(container.querySelector('.card-body')).toHaveAttribute('class', expect.stringContaining(expectedCardClass));
|
||||
expect(screen.getByRole('heading')).toHaveClass(`text-center mb-0 ${expectedH3Class}`);
|
||||
});
|
||||
|
||||
it.each([{ className: 'foo' }, { className: 'bar' }, {}])('renders provided classes', ({ className }) => {
|
||||
const { container } = setUp({ className });
|
||||
expect(container.firstChild).toHaveClass(`g-0${className ? ` ${className}` : ''}`);
|
||||
});
|
||||
});
|
||||
33
shlink-frontend-kit/test/block/Result.test.tsx
Normal file
33
shlink-frontend-kit/test/block/Result.test.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import type { ResultProps, ResultType } from '../../src';
|
||||
import { Result } from '../../src';
|
||||
|
||||
describe('<Result />', () => {
|
||||
const setUp = (props: ResultProps) => render(<Result {...props} />);
|
||||
|
||||
it.each([
|
||||
['success' as ResultType, 'bg-main text-white'],
|
||||
['error' as ResultType, 'bg-danger text-white'],
|
||||
['warning' as ResultType, 'bg-warning'],
|
||||
])('renders expected classes based on type', (type, expectedClasses) => {
|
||||
setUp({ type });
|
||||
expect(screen.getByRole('document')).toHaveClass(expectedClasses);
|
||||
});
|
||||
|
||||
it.each([
|
||||
['foo'],
|
||||
['bar'],
|
||||
])('renders provided classes in root element', (className) => {
|
||||
const { container } = setUp({ type: 'success', className });
|
||||
expect(container.firstChild).toHaveClass(className);
|
||||
});
|
||||
|
||||
it.each([{ small: true }, { small: false }])('renders small results properly', ({ small }) => {
|
||||
const { container } = setUp({ type: 'success', small });
|
||||
const bigElement = container.querySelectorAll('.col-md-10');
|
||||
const smallElement = container.querySelectorAll('.col-12');
|
||||
|
||||
expect(bigElement).toHaveLength(small ? 0 : 1);
|
||||
expect(smallElement).toHaveLength(small ? 1 : 0);
|
||||
});
|
||||
});
|
||||
27
shlink-frontend-kit/test/block/SimpleCard.test.tsx
Normal file
27
shlink-frontend-kit/test/block/SimpleCard.test.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import type { SimpleCardProps } from '../../src';
|
||||
import { SimpleCard } from '../../src';
|
||||
|
||||
const setUp = ({ children, ...rest }: SimpleCardProps = {}) => render(<SimpleCard {...rest}>{children}</SimpleCard>);
|
||||
|
||||
describe('<SimpleCard />', () => {
|
||||
it('does not render title if not provided', () => {
|
||||
setUp();
|
||||
expect(screen.queryByRole('heading')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders provided title', () => {
|
||||
setUp({ title: 'Cool title' });
|
||||
expect(screen.getByRole('heading')).toHaveTextContent('Cool title');
|
||||
});
|
||||
|
||||
it('renders children inside body', () => {
|
||||
setUp({ children: 'Hello world' });
|
||||
expect(screen.getByText('Hello world')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it.each(['primary', 'danger', 'warning'])('passes extra props to nested card', (color) => {
|
||||
const { container } = setUp({ className: 'foo', color, children: 'Hello world' });
|
||||
expect(container.firstChild).toHaveAttribute('class', `foo card bg-${color}`);
|
||||
});
|
||||
});
|
||||
44
shlink-frontend-kit/test/form/Checkbox.test.tsx
Normal file
44
shlink-frontend-kit/test/form/Checkbox.test.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { Checkbox } from '../../src';
|
||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||
|
||||
describe('<Checkbox />', () => {
|
||||
it.each([['foo'], ['bar'], ['baz']])('includes extra class names when provided', (className) => {
|
||||
const { container } = render(<Checkbox className={className} />);
|
||||
expect(container.firstChild).toHaveAttribute('class', `form-check form-checkbox ${className}`);
|
||||
});
|
||||
|
||||
it.each([[true], [false]])('marks input as checked if defined', (checked) => {
|
||||
render(<Checkbox checked={checked}>Foo</Checkbox>);
|
||||
|
||||
if (checked) {
|
||||
expect(screen.getByLabelText('Foo')).toBeChecked();
|
||||
} else {
|
||||
expect(screen.getByLabelText('Foo')).not.toBeChecked();
|
||||
}
|
||||
});
|
||||
|
||||
it.each([['foo'], ['bar'], ['baz']])('renders provided children inside the label', (children) => {
|
||||
render(<Checkbox>{children}</Checkbox>);
|
||||
expect(screen.getByText(children)).toHaveAttribute('class', 'form-check-label');
|
||||
});
|
||||
|
||||
it.each([[true], [false]])('changes checked status on input change', async (checked) => {
|
||||
const onChange = vi.fn();
|
||||
const { user } = renderWithEvents(<Checkbox onChange={onChange} checked={checked}>Foo</Checkbox>);
|
||||
|
||||
expect(onChange).not.toHaveBeenCalled();
|
||||
await user.click(screen.getByLabelText('Foo'));
|
||||
expect(onChange).toHaveBeenCalledWith(!checked, expect.anything());
|
||||
});
|
||||
|
||||
it.each([[true], [false]])('allows setting inline rendering', (inline) => {
|
||||
const { container } = render(<Checkbox inline={inline} />);
|
||||
|
||||
if (inline) {
|
||||
expect(container.firstChild).toHaveAttribute('style', 'display: inline-block;');
|
||||
} else {
|
||||
expect(container.firstChild).not.toHaveAttribute('style');
|
||||
}
|
||||
});
|
||||
});
|
||||
47
shlink-frontend-kit/test/navigation/DropdownBtn.test.tsx
Normal file
47
shlink-frontend-kit/test/navigation/DropdownBtn.test.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
import { screen } from '@testing-library/react';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import type { DropdownBtnProps } from '../../src';
|
||||
import { DropdownBtn } from '../../src';
|
||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||
|
||||
describe('<DropdownBtn />', () => {
|
||||
const setUp = (props: PropsWithChildren<DropdownBtnProps>) => renderWithEvents(
|
||||
<DropdownBtn children="foo" {...props} />,
|
||||
);
|
||||
|
||||
it.each([['foo'], ['bar'], ['baz']])('displays provided text in button', (text) => {
|
||||
setUp({ text });
|
||||
expect(screen.getByRole('button')).toHaveTextContent(text);
|
||||
});
|
||||
|
||||
it.each([['foo'], ['bar'], ['baz']])('displays provided children in menu', async (children) => {
|
||||
const { user } = setUp({ text: '', children });
|
||||
|
||||
await user.click(screen.getByRole('button'));
|
||||
expect(screen.getByRole('menu')).toHaveTextContent(children);
|
||||
});
|
||||
|
||||
it.each([
|
||||
[undefined, 'dropdown-btn__toggle btn-block'],
|
||||
['', 'dropdown-btn__toggle btn-block'],
|
||||
['foo', 'dropdown-btn__toggle btn-block foo'],
|
||||
['bar', 'dropdown-btn__toggle btn-block bar'],
|
||||
])('includes provided classes', (className, expectedClasses) => {
|
||||
setUp({ text: '', className });
|
||||
expect(screen.getByRole('button')).toHaveClass(expectedClasses);
|
||||
});
|
||||
|
||||
it.each([
|
||||
[100, 'min-width: 100px; '],
|
||||
[250, 'min-width: 250px; '],
|
||||
[undefined, ''],
|
||||
])('renders proper styles when minWidth is provided', async (minWidth, expectedStyle) => {
|
||||
const { user } = setUp({ text: '', minWidth });
|
||||
|
||||
await user.click(screen.getByRole('button'));
|
||||
expect(screen.getByRole('menu')).toHaveAttribute(
|
||||
'style',
|
||||
`${expectedStyle}position: absolute; left: 0px; top: 0px; transform: translate(0px, 0px);`,
|
||||
);
|
||||
});
|
||||
});
|
||||
56
shlink-frontend-kit/test/navigation/NavPills.test.tsx
Normal file
56
shlink-frontend-kit/test/navigation/NavPills.test.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
/* eslint-disable no-console */
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { NavPillItem, NavPills } from '../../src';
|
||||
|
||||
describe('<NavPills />', () => {
|
||||
let originalError: typeof console.error;
|
||||
|
||||
beforeEach(() => {
|
||||
originalError = console.error;
|
||||
console.error = () => {}; // Suppress errors logged during this test
|
||||
});
|
||||
afterEach(() => {
|
||||
console.error = originalError;
|
||||
});
|
||||
|
||||
it.each([
|
||||
['Foo'],
|
||||
[<span key="1">Hi!</span>],
|
||||
[[<NavPillItem key="1" to="" />, <span key="2">Hi!</span>]],
|
||||
])('throws error when any of the children is not a NavPillItem', (children) => {
|
||||
expect.assertions(1);
|
||||
expect(() => render(<NavPills>{children}</NavPills>)).toThrow(
|
||||
'Only NavPillItem children are allowed inside NavPills.',
|
||||
);
|
||||
});
|
||||
|
||||
it.each([
|
||||
[undefined],
|
||||
[true],
|
||||
[false],
|
||||
])('renders provided items', (fill) => {
|
||||
const { container } = render(
|
||||
<MemoryRouter>
|
||||
<NavPills fill={fill}>
|
||||
<NavPillItem to="1">1</NavPillItem>
|
||||
<NavPillItem to="2">2</NavPillItem>
|
||||
<NavPillItem to="3">3</NavPillItem>
|
||||
</NavPills>
|
||||
</MemoryRouter>,
|
||||
);
|
||||
|
||||
const links = screen.getAllByRole('link');
|
||||
expect(links).toHaveLength(3);
|
||||
links.forEach((link, index) => {
|
||||
expect(link).toHaveTextContent(`${index + 1}`);
|
||||
expect(link).toHaveAttribute('href', `/${index + 1}`);
|
||||
});
|
||||
|
||||
if (fill) {
|
||||
expect(container.querySelector('.nav')).toHaveClass('nav-fill');
|
||||
} else {
|
||||
expect(container.querySelector('.nav')).not.toHaveClass('nav-fill');
|
||||
}
|
||||
});
|
||||
});
|
||||
28
shlink-frontend-kit/test/navigation/RowDropdownBtn.test.tsx
Normal file
28
shlink-frontend-kit/test/navigation/RowDropdownBtn.test.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import { screen } from '@testing-library/react';
|
||||
import { fromPartial } from '@total-typescript/shoehorn';
|
||||
import type { DropdownBtnMenuProps } from '../../src';
|
||||
import { RowDropdownBtn } from '../../src';
|
||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||
|
||||
describe('<RowDropdownBtn />', () => {
|
||||
const setUp = (props: Partial<DropdownBtnMenuProps> = {}) => renderWithEvents(
|
||||
<RowDropdownBtn {...fromPartial<DropdownBtnMenuProps>({ ...props })}>
|
||||
the children
|
||||
</RowDropdownBtn>,
|
||||
);
|
||||
|
||||
it('renders expected components', () => {
|
||||
setUp();
|
||||
const toggle = screen.getByRole('button');
|
||||
|
||||
expect(toggle).toBeInTheDocument();
|
||||
expect(toggle).toHaveClass('btn-sm');
|
||||
expect(toggle).toHaveClass('dropdown-btn__toggle');
|
||||
expect(screen.getByRole('img', { hidden: true })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders expected children', () => {
|
||||
setUp();
|
||||
expect(screen.getByText('the children')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
107
shlink-frontend-kit/test/ordering/OrderingDropdown.test.tsx
Normal file
107
shlink-frontend-kit/test/ordering/OrderingDropdown.test.tsx
Normal file
@@ -0,0 +1,107 @@
|
||||
import { screen } from '@testing-library/react';
|
||||
import { values } from 'ramda';
|
||||
import type { OrderDir, OrderingDropdownProps } from '../../src';
|
||||
import { OrderingDropdown } from '../../src';
|
||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||
|
||||
describe('<OrderingDropdown />', () => {
|
||||
const items = {
|
||||
foo: 'Foo',
|
||||
bar: 'Bar',
|
||||
baz: 'Hello World',
|
||||
};
|
||||
const setUp = (props: Partial<OrderingDropdownProps> = {}) => renderWithEvents(
|
||||
<OrderingDropdown items={items} order={{}} onChange={vi.fn()} {...props} />,
|
||||
);
|
||||
const setUpWithDisplayedMenu = async (props: Partial<OrderingDropdownProps> = {}) => {
|
||||
const result = setUp(props);
|
||||
const { user } = result;
|
||||
|
||||
await user.click(screen.getByRole('button'));
|
||||
expect(await screen.findByRole('menu')).toBeInTheDocument();
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
it('properly renders provided list of items', async () => {
|
||||
await setUpWithDisplayedMenu();
|
||||
|
||||
const dropdownItems = screen.getAllByRole('menuitem');
|
||||
|
||||
expect(dropdownItems).toHaveLength(values(items).length);
|
||||
expect(dropdownItems[0]).toHaveTextContent('Foo');
|
||||
expect(dropdownItems[1]).toHaveTextContent('Bar');
|
||||
expect(dropdownItems[2]).toHaveTextContent('Hello World');
|
||||
expect(screen.getByRole('button', { name: 'Clear selection' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it.each([
|
||||
['foo', 0],
|
||||
['bar', 1],
|
||||
['baz', 2],
|
||||
])('properly marks selected field as active with proper icon', async (field, expectedActiveIndex) => {
|
||||
await setUpWithDisplayedMenu({ order: { field, dir: 'DESC' } });
|
||||
|
||||
const dropdownItems = screen.getAllByRole('menuitem');
|
||||
|
||||
expect(dropdownItems).toHaveLength(4);
|
||||
expect(screen.queryByRole('button', { name: 'Clear selection' })).not.toBeInTheDocument();
|
||||
|
||||
dropdownItems.forEach((item, index) => {
|
||||
if (index === expectedActiveIndex) {
|
||||
expect(item).toHaveAttribute('class', expect.stringContaining('active'));
|
||||
} else {
|
||||
expect(item).not.toHaveAttribute('class', expect.stringContaining('active'));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it.each([
|
||||
[{} as any, 'foo', 'ASC'],
|
||||
[{ field: 'baz', dir: 'ASC' } as any, 'foo', 'ASC'],
|
||||
[{ field: 'foo', dir: 'ASC' } as any, 'foo', 'DESC'],
|
||||
[{ field: 'foo', dir: 'DESC' } as any, undefined, undefined],
|
||||
])(
|
||||
'triggers change with proper params depending on clicked item and initial state',
|
||||
async (initialOrder, expectedNewField, expectedNewDir) => {
|
||||
const onChange = vi.fn();
|
||||
const { user } = await setUpWithDisplayedMenu({ onChange, order: initialOrder });
|
||||
|
||||
await user.click(screen.getAllByRole('menuitem')[0]);
|
||||
|
||||
expect(onChange).toHaveBeenCalledTimes(1);
|
||||
expect(onChange).toHaveBeenCalledWith(expectedNewField, expectedNewDir);
|
||||
},
|
||||
);
|
||||
|
||||
it('clears selection when last item is clicked', async () => {
|
||||
const onChange = vi.fn();
|
||||
const { user } = await setUpWithDisplayedMenu({ onChange, order: { field: 'baz', dir: 'ASC' } });
|
||||
|
||||
await user.click(screen.getAllByRole('menuitem')[3]);
|
||||
|
||||
expect(onChange).toHaveBeenCalledTimes(1);
|
||||
expect(onChange).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it.each([
|
||||
[{ isButton: false }, /Order by$/],
|
||||
[{ isButton: true }, 'Order by...'],
|
||||
[
|
||||
{ isButton: true, order: { field: 'foo', dir: 'ASC' as OrderDir } },
|
||||
'Order by: Foo - ASC',
|
||||
],
|
||||
[
|
||||
{ isButton: true, order: { field: 'baz', dir: 'DESC' as OrderDir } },
|
||||
'Order by: Hello World - DESC',
|
||||
],
|
||||
[{ isButton: true, order: { field: 'baz' } }, 'Order by: Hello World - DESC'],
|
||||
[
|
||||
{ isButton: true, order: { field: 'baz', dir: 'DESC' as OrderDir }, prefixed: false },
|
||||
/^Hello World - DESC/,
|
||||
],
|
||||
])('with %s props displays %s in toggle', async (props, expectedText) => {
|
||||
setUp(props);
|
||||
expect(screen.getByRole('button')).toHaveTextContent(expectedText);
|
||||
});
|
||||
});
|
||||
46
shlink-frontend-kit/test/ordering/ordering.test.ts
Normal file
46
shlink-frontend-kit/test/ordering/ordering.test.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import type { OrderDir } from '../../src';
|
||||
import { determineOrderDir, orderToString, stringToOrder } from '../../src';
|
||||
|
||||
describe('ordering', () => {
|
||||
describe('determineOrderDir', () => {
|
||||
it('returns ASC when current order field and selected field are different', () => {
|
||||
expect(determineOrderDir('foo', 'bar')).toEqual('ASC');
|
||||
expect(determineOrderDir('bar', 'foo')).toEqual('ASC');
|
||||
});
|
||||
|
||||
it('returns ASC when no current order dir is provided', () => {
|
||||
expect(determineOrderDir('foo', 'foo')).toEqual('ASC');
|
||||
expect(determineOrderDir('bar', 'bar')).toEqual('ASC');
|
||||
});
|
||||
|
||||
it('returns DESC when current order field and selected field are equal and current order dir is ASC', () => {
|
||||
expect(determineOrderDir('foo', 'foo', 'ASC')).toEqual('DESC');
|
||||
expect(determineOrderDir('bar', 'bar', 'ASC')).toEqual('DESC');
|
||||
});
|
||||
|
||||
it('returns undefined when current order field and selected field are equal and current order dir is DESC', () => {
|
||||
expect(determineOrderDir('foo', 'foo', 'DESC')).toBeUndefined();
|
||||
expect(determineOrderDir('bar', 'bar', 'DESC')).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('orderToString', () => {
|
||||
it.each([
|
||||
[{}, undefined],
|
||||
[{ field: 'foo' }, undefined],
|
||||
[{ field: 'foo', dir: 'ASC' as OrderDir }, 'foo-ASC'],
|
||||
[{ field: 'bar', dir: 'DESC' as OrderDir }, 'bar-DESC'],
|
||||
])('casts the order to string', (order, expectedResult) => {
|
||||
expect(orderToString(order)).toEqual(expectedResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('stringToOrder', () => {
|
||||
it.each([
|
||||
['foo-ASC', { field: 'foo', dir: 'ASC' }],
|
||||
['bar-DESC', { field: 'bar', dir: 'DESC' }],
|
||||
])('casts a string to an order objects', (order, expectedResult) => {
|
||||
expect(stringToOrder(order)).toEqual(expectedResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user