add tests for sort picker and update select tests
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import '@testing-library/jest-dom';
|
||||
import { fireEvent, waitFor } from '@testing-library/preact';
|
||||
import { h } from 'preact';
|
||||
import { render } from 'tests/utils';
|
||||
import { Select } from './select';
|
||||
@@ -29,18 +30,31 @@ const items = [
|
||||
describe('<Select/>', () => {
|
||||
it('should has static class names', () => {
|
||||
const { container } = render(<Select items={items} selected={items[0]} />);
|
||||
const selectElement = container.querySelector('.select-element');
|
||||
|
||||
expect(container.querySelector('.select')).toBeInTheDocument();
|
||||
expect(container.querySelector('.select-arrow')).toBeInTheDocument();
|
||||
expect(container.querySelector('.select-element')).toBeInTheDocument();
|
||||
expect(selectElement).toBeInTheDocument();
|
||||
fireEvent.focus(selectElement as HTMLSelectElement);
|
||||
expect(container.querySelector('.select_focused')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render selected item', () => {
|
||||
const { container, getAllByText } = render(<Select items={items} selected={items[0]} />);
|
||||
const selectedOption = container.querySelectorAll('option')[0];
|
||||
const selectedOption = container.querySelector('option');
|
||||
|
||||
expect(getAllByText(items[0].label)).toHaveLength(2);
|
||||
expect(selectedOption.selected).toBeTruthy();
|
||||
expect(selectedOption.textContent).toBe(items[0].label);
|
||||
expect(selectedOption).toBeInTheDocument();
|
||||
expect(selectedOption?.selected).toBeTruthy();
|
||||
expect(selectedOption?.textContent).toBe(items[0].label);
|
||||
});
|
||||
|
||||
it('should highlight selet on focus', async () => {
|
||||
const { container } = render(<Select items={items} selected={items[0]} />);
|
||||
const select = container.querySelector('select');
|
||||
|
||||
expect(container.querySelector('select')).toBeInTheDocument();
|
||||
fireEvent.focus(select as HTMLSelectElement);
|
||||
expect(container.querySelector('.rootFocused')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -12,21 +12,20 @@ type Item = {
|
||||
type Props = {
|
||||
items: Item[];
|
||||
selected: Item;
|
||||
onChange?: JSX.GenericEventHandler<HTMLSelectElement>;
|
||||
};
|
||||
} & Omit<JSX.HTMLAttributes<HTMLSelectElement>, 'className' | 'onFocus' | 'onBlur' | 'selected'>;
|
||||
|
||||
export function Select({ items, selected, onChange }: Props) {
|
||||
export function Select({ items, selected, ...props }: Props) {
|
||||
const [focus, setFocus] = useState(false);
|
||||
|
||||
return (
|
||||
<span className={clsx('select', styles.root, focus && styles.rootFocused)}>
|
||||
<span className={clsx('select', styles.root, { [styles.rootFocused]: focus, select_focused: focus })}>
|
||||
{selected.label}
|
||||
<Arrow className={clsx('select-arrow', styles.arrow)} />
|
||||
<select
|
||||
{...props}
|
||||
onFocus={() => setFocus(true)}
|
||||
onBlur={() => setFocus(false)}
|
||||
className={clsx('select-element', styles.select)}
|
||||
onChange={onChange}
|
||||
>
|
||||
{items.map((i) => (
|
||||
<option key={i.value} value={i.value} selected={selected.value === i.value}>
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import '@testing-library/jest-dom';
|
||||
import { fireEvent, waitFor } from '@testing-library/preact';
|
||||
import { h } from 'preact';
|
||||
|
||||
import { render } from 'tests/utils';
|
||||
import * as commentsActions from 'store/comments/actions';
|
||||
import * as localStorage from 'common/local-storage';
|
||||
import { LS_SORT_KEY } from 'common/constants';
|
||||
import type { Tree } from 'common/types';
|
||||
import type { StoreState } from 'store';
|
||||
|
||||
import { SortPicker } from './sort-picker';
|
||||
|
||||
const defaultState = { comments: {} as StoreState['comments'], hiddenUsers: {} };
|
||||
const stateWithSort = { comments: { sort: '-active' } as StoreState['comments'] };
|
||||
|
||||
describe('<SortPicker />', () => {
|
||||
it('should render sort picker with options', () => {
|
||||
const { container, queryAllByText, queryByText } = render(<SortPicker />, defaultState);
|
||||
|
||||
expect(container.querySelectorAll('option')).toHaveLength(8);
|
||||
expect(queryAllByText('Best')).toHaveLength(2);
|
||||
expect(queryByText('Sort by')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should has static class names', () => {
|
||||
const { container } = render(<SortPicker />, defaultState);
|
||||
|
||||
expect(container.querySelector('.sort-picker')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render selected element', () => {
|
||||
const { container, queryAllByText } = render(<SortPicker />, stateWithSort);
|
||||
|
||||
expect(queryAllByText('Recently updated')).toHaveLength(2);
|
||||
expect(container.querySelector<HTMLOptionElement>('[value="-active"]')?.selected).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should change selected store', async () => {
|
||||
const nextOption = '-controversy';
|
||||
const updateSorting = jest.spyOn(commentsActions, 'updateSorting');
|
||||
const { container } = render(<SortPicker />, defaultState);
|
||||
const select = container.querySelector('select') as HTMLSelectElement;
|
||||
|
||||
expect(select).toBeInTheDocument();
|
||||
|
||||
fireEvent.change(select, { target: { value: nextOption } });
|
||||
|
||||
await waitFor(() => expect(updateSorting).toHaveBeenCalledWith(nextOption));
|
||||
|
||||
expect(container.querySelector<HTMLOptionElement>(`[value="${nextOption}"]`)?.selected).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,7 +13,6 @@ import styles from './sort-picker.module.css';
|
||||
|
||||
export function SortPicker() {
|
||||
const dispatch = useDispatch();
|
||||
const sort = useSelector((s: StoreState) => s.comments.sort);
|
||||
const intl = useIntl();
|
||||
const [items, itemsById] = useMemo(() => {
|
||||
const sortOptions = {
|
||||
@@ -27,14 +26,16 @@ export function SortPicker() {
|
||||
'+controversy': intl.formatMessage(messages.leastControversial),
|
||||
};
|
||||
type SortItem = { value: string; label: string };
|
||||
const sort: SortItem[] = Object.entries(sortOptions).map(([k, v]) => ({ value: k, label: v }));
|
||||
const sortById = sort.reduce(
|
||||
const sortItems: SortItem[] = Object.entries(sortOptions).map(([k, v]) => ({ value: k, label: v }));
|
||||
const sortById = sortItems.reduce(
|
||||
(accum, s) => ({ ...accum, [s.value]: s }),
|
||||
{} as Record<keyof typeof sortOptions, SortItem>
|
||||
);
|
||||
|
||||
return [sort, sortById];
|
||||
return [sortItems, sortById];
|
||||
}, []);
|
||||
const sort = useSelector((s: StoreState) => s.comments.sort) || items[0].value;
|
||||
const selected = itemsById[sort];
|
||||
|
||||
function handleSortChange(evt: Event) {
|
||||
const { value } = evt.target as HTMLOptionElement;
|
||||
@@ -49,7 +50,7 @@ export function SortPicker() {
|
||||
return (
|
||||
<span className={clsx('sort-picker', styles.root)}>
|
||||
<FormattedMessage id="sort-by" defaultMessage="Sort by" />{' '}
|
||||
<Select items={items} selected={itemsById[sort]} onChange={handleSortChange} />
|
||||
<Select items={items} selected={selected} onChange={handleSortChange} />
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
import { h, ComponentChild } from 'preact';
|
||||
import { IntlProvider } from 'react-intl';
|
||||
import { render as originalRender } from '@testing-library/preact';
|
||||
import { Provider } from 'react-redux';
|
||||
|
||||
import en from 'locales/en.json';
|
||||
import { mockStore } from '__stubs__/store';
|
||||
import { StoreState } from 'store';
|
||||
|
||||
export function render(children: ComponentChild) {
|
||||
export function render(children: ComponentChild, s: Partial<StoreState> = {}) {
|
||||
return originalRender(
|
||||
<IntlProvider locale="en" messages={en}>
|
||||
{children}
|
||||
<Provider store={mockStore(s)}>{children}</Provider>
|
||||
</IntlProvider>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user