mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-02 09:15:22 +03:00
improved Select.test.jsx
This commit is contained in:
parent
4e5a368a97
commit
313deb986b
@ -53,7 +53,7 @@ export const DateFilterOptions = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Custom Range',
|
label: 'Custom Range',
|
||||||
value: null,
|
value: 'custom_range',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -134,6 +134,7 @@ export default function DatePicker({
|
|||||||
tabIndex="0"
|
tabIndex="0"
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
value={propValue}
|
value={propValue}
|
||||||
|
{...props}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
className={`absolute top-3 transition transform text-gray-600 dark:text-gray-400 ${
|
className={`absolute top-3 transition transform text-gray-600 dark:text-gray-400 ${
|
||||||
|
|||||||
@ -76,19 +76,20 @@ export default function Select({
|
|||||||
const ref = useRef(null);
|
const ref = useRef(null);
|
||||||
|
|
||||||
const handleSelect = useCallback(
|
const handleSelect = useCallback(
|
||||||
(value, label) => {
|
(value) => {
|
||||||
setSelected(options.findIndex(({ value }) => Object.values(propSelected).includes(value)));
|
setSelected(options.findIndex(({ value }) => Object.values(propSelected).includes(value)));
|
||||||
setShowMenu(false);
|
setShowMenu(false);
|
||||||
|
|
||||||
if (!value) return setShowDatePicker(true);
|
//show calender date range picker
|
||||||
onChange && onChange(value, label);
|
if (value === 'custom_range') return setShowDatePicker(true);
|
||||||
|
onChange && onChange(value);
|
||||||
},
|
},
|
||||||
[onChange, options, propSelected, setSelected]
|
[onChange, options, propSelected, setSelected]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleDateRange = useCallback(
|
const handleDateRange = useCallback(
|
||||||
(range) => {
|
(range) => {
|
||||||
onChange && onChange(range, 'range');
|
onChange && onChange(range);
|
||||||
setShowMenu(false);
|
setShowMenu(false);
|
||||||
},
|
},
|
||||||
[onChange]
|
[onChange]
|
||||||
@ -98,6 +99,44 @@ export default function Select({
|
|||||||
setShowMenu(true);
|
setShowMenu(true);
|
||||||
}, [setShowMenu]);
|
}, [setShowMenu]);
|
||||||
|
|
||||||
|
const handleKeydownDatePicker = useCallback(
|
||||||
|
(event) => {
|
||||||
|
switch (event.key) {
|
||||||
|
case 'Enter': {
|
||||||
|
if (!showMenu) {
|
||||||
|
setShowMenu(true);
|
||||||
|
setFocused(selected);
|
||||||
|
} else {
|
||||||
|
setSelected(focused);
|
||||||
|
if (options[focused].value === 'custom_range') {
|
||||||
|
setShowMenu(false);
|
||||||
|
return setShowDatePicker(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
onChange && onChange(options[focused].value);
|
||||||
|
setShowMenu(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'ArrowDown': {
|
||||||
|
const newIndex = focused + 1;
|
||||||
|
newIndex < options.length && setFocused(newIndex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'ArrowUp': {
|
||||||
|
const newIndex = focused - 1;
|
||||||
|
newIndex > -1 && setFocused(newIndex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no default
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[onChange, options, showMenu, setShowMenu, setFocused, focused, selected]
|
||||||
|
);
|
||||||
|
|
||||||
const handleKeydown = useCallback(
|
const handleKeydown = useCallback(
|
||||||
(event) => {
|
(event) => {
|
||||||
switch (event.key) {
|
switch (event.key) {
|
||||||
@ -107,7 +146,7 @@ export default function Select({
|
|||||||
setFocused(selected);
|
setFocused(selected);
|
||||||
} else {
|
} else {
|
||||||
setSelected(focused);
|
setSelected(focused);
|
||||||
onChange && onChange(options[focused].value, options[focused].label);
|
onChange && onChange({ [paramName]: options[focused].value });
|
||||||
setShowMenu(false);
|
setShowMenu(false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -146,7 +185,7 @@ export default function Select({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
window.addEventListener('click', addBackDrop);
|
window.addEventListener('click', addBackDrop);
|
||||||
// setDateToInput(state.selectedDay);
|
|
||||||
return function cleanup() {
|
return function cleanup() {
|
||||||
window.removeEventListener('click', addBackDrop);
|
window.removeEventListener('click', addBackDrop);
|
||||||
};
|
};
|
||||||
@ -161,7 +200,7 @@ export default function Select({
|
|||||||
label={label}
|
label={label}
|
||||||
onchange={onChange}
|
onchange={onChange}
|
||||||
onclick={handleClick}
|
onclick={handleClick}
|
||||||
onkeydown={handleKeydown}
|
onkeydown={handleKeydownDatePicker}
|
||||||
trailingIcon={showMenu ? ArrowDropup : ArrowDropdown}
|
trailingIcon={showMenu ? ArrowDropup : ArrowDropdown}
|
||||||
value={datePickerValue}
|
value={datePickerValue}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -4,6 +4,30 @@ import { fireEvent, render, screen } from '@testing-library/preact';
|
|||||||
|
|
||||||
describe('Select', () => {
|
describe('Select', () => {
|
||||||
test('on focus, shows a menu', async () => {
|
test('on focus, shows a menu', async () => {
|
||||||
|
const handleChange = jest.fn();
|
||||||
|
render(
|
||||||
|
<Select
|
||||||
|
label="Tacos"
|
||||||
|
type="dropdown"
|
||||||
|
onChange={handleChange}
|
||||||
|
options={['all', 'tacos', 'burritos']}
|
||||||
|
paramName={['dinner']}
|
||||||
|
selected=""
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.queryByRole('listbox')).not.toBeInTheDocument();
|
||||||
|
fireEvent.click(screen.getByRole('textbox'));
|
||||||
|
expect(screen.queryByRole('listbox')).toBeInTheDocument();
|
||||||
|
expect(screen.queryByRole('option', { name: 'all' })).toBeInTheDocument();
|
||||||
|
expect(screen.queryByRole('option', { name: 'tacos' })).toBeInTheDocument();
|
||||||
|
expect(screen.queryByRole('option', { name: 'burritos' })).toBeInTheDocument();
|
||||||
|
|
||||||
|
fireEvent.click(screen.queryByRole('option', { name: 'tacos' }));
|
||||||
|
expect(handleChange).toHaveBeenCalledWith({ dinner: 'tacos' });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('allows keyboard navigation', async () => {
|
||||||
const handleChange = jest.fn();
|
const handleChange = jest.fn();
|
||||||
render(
|
render(
|
||||||
<Select
|
<Select
|
||||||
@ -17,27 +41,13 @@ describe('Select', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(screen.queryByRole('listbox')).not.toBeInTheDocument();
|
expect(screen.queryByRole('listbox')).not.toBeInTheDocument();
|
||||||
fireEvent.click(screen.getByRole('textbox'));
|
const input = screen.getByRole('textbox');
|
||||||
|
fireEvent.focus(input);
|
||||||
|
fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });
|
||||||
expect(screen.queryByRole('listbox')).toBeInTheDocument();
|
expect(screen.queryByRole('listbox')).toBeInTheDocument();
|
||||||
expect(screen.queryByRole('option', { name: 'tacos' })).toBeInTheDocument();
|
|
||||||
expect(screen.queryByRole('option', { name: 'burritos' })).toBeInTheDocument();
|
|
||||||
|
|
||||||
fireEvent.click(screen.queryByRole('option', { name: 'tacos' }));
|
fireEvent.keyDown(input, { key: 'ArrowDown', code: 'ArrowDown' });
|
||||||
expect(handleChange).toHaveBeenCalledWith({ dinner: 'tacos' }, 'tacos');
|
fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });
|
||||||
|
expect(handleChange).toHaveBeenCalledWith({ dinner: 'burritos' });
|
||||||
});
|
});
|
||||||
|
|
||||||
// test('allows keyboard navigation', async () => {
|
|
||||||
// const handleChange = jest.fn();
|
|
||||||
// render(<Select label="Tacos" onChange={handleChange} options={['tacos', 'burritos']} paramName={['burritos']} />);
|
|
||||||
|
|
||||||
// expect(screen.queryByRole('listbox')).not.toBeInTheDocument();
|
|
||||||
// const input = screen.getByRole('textbox');
|
|
||||||
// fireEvent.focus(input);
|
|
||||||
// fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });
|
|
||||||
// expect(screen.queryByRole('listbox')).toBeInTheDocument();
|
|
||||||
|
|
||||||
// fireEvent.keyDown(input, { key: 'ArrowDown', code: 'ArrowDown' });
|
|
||||||
// fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });
|
|
||||||
// expect(handleChange).toHaveBeenCalledWith('burritos', 'burritos');
|
|
||||||
// });
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { h } from 'preact';
|
|||||||
import Select from '../../../components/Select';
|
import Select from '../../../components/Select';
|
||||||
import { useCallback } from 'preact/hooks';
|
import { useCallback } from 'preact/hooks';
|
||||||
|
|
||||||
function Filter({ onChange, searchParams, paramName, options, type, ...rest }) {
|
function Filter({ onChange, searchParams, paramName, options, ...rest }) {
|
||||||
const handleSelect = useCallback(
|
const handleSelect = useCallback(
|
||||||
(key) => {
|
(key) => {
|
||||||
const newParams = new URLSearchParams(searchParams.toString());
|
const newParams = new URLSearchParams(searchParams.toString());
|
||||||
@ -20,10 +20,7 @@ function Filter({ onChange, searchParams, paramName, options, type, ...rest }) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const obj = {};
|
const obj = {};
|
||||||
paramName.map((p) => Object.assign(obj, { [p]: searchParams.get(p) }), [searchParams]);
|
paramName.map((name) => Object.assign(obj, { [name]: searchParams.get(name) }), [searchParams]);
|
||||||
|
return <Select onChange={handleSelect} options={options} selected={obj} paramName={paramName} {...rest} />;
|
||||||
return (
|
|
||||||
<Select onChange={handleSelect} options={options} selected={obj} paramName={paramName} type={type} {...rest} />
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
export default Filter;
|
export default Filter;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user