mirror of
https://github.com/qlik-oss/nebula.js.git
synced 2025-12-25 01:04:14 -05:00
fix: Esc key down doesn't close searchbox (#1544)
* fix: Esckey on ListBoxSearch doesn't close the searchbox
This commit is contained in:
committed by
GitHub
parent
7fd2fcc97f
commit
d6cb5aa122
@@ -192,6 +192,7 @@ export default function ListBoxPopover({
|
||||
<div ref={moreAlignTo} />
|
||||
<Grid item ref={searchContainerRef}>
|
||||
<ListBoxSearch
|
||||
popoverOpen={open}
|
||||
styles={styles}
|
||||
visible
|
||||
model={model}
|
||||
|
||||
@@ -59,6 +59,7 @@ const StyledOutlinedInput = styled(OutlinedInput, {
|
||||
});
|
||||
|
||||
export default function ListBoxSearch({
|
||||
popoverOpen,
|
||||
selections,
|
||||
selectionState,
|
||||
model,
|
||||
@@ -75,7 +76,6 @@ export default function ListBoxSearch({
|
||||
const { translator } = useContext(InstanceContext);
|
||||
const [value, setValue] = useState('');
|
||||
const [wildcardOn, setWildcardOn] = useState(false);
|
||||
|
||||
const inputRef = useRef();
|
||||
|
||||
const { getStoreValue, setStoreValue } = useDataStore(model);
|
||||
@@ -171,6 +171,9 @@ export default function ListBoxSearch({
|
||||
case 'Escape': {
|
||||
focusRow(container);
|
||||
cancel();
|
||||
if (popoverOpen) {
|
||||
return undefined;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'Tab': {
|
||||
|
||||
@@ -20,16 +20,21 @@ const styles = { content: {}, header: {}, selections: {}, search: {}, background
|
||||
const keyboard = {};
|
||||
let selectionState;
|
||||
|
||||
const hide = jest.fn().mockReturnValue(true);
|
||||
let open = false;
|
||||
|
||||
const testRender = (model) =>
|
||||
create(
|
||||
<InstanceContext.Provider value={{ translator: { get: () => 'Search' } }}>
|
||||
<ListBoxSearch
|
||||
popoverOpen={open}
|
||||
styles={styles}
|
||||
selections={selections}
|
||||
model={model}
|
||||
keyboard={keyboard}
|
||||
selectionState={selectionState}
|
||||
wildCardSearch
|
||||
hide={hide}
|
||||
/>
|
||||
</InstanceContext.Provider>
|
||||
);
|
||||
@@ -56,6 +61,7 @@ describe('<ListBoxSearch />', () => {
|
||||
|
||||
keyboard.innerTabStops = true;
|
||||
keyboard.outerTabStops = !keyboard.innerTabStops;
|
||||
open = false;
|
||||
|
||||
model = {
|
||||
searchListObjectFor: jest.fn().mockResolvedValue(true),
|
||||
@@ -205,7 +211,7 @@ describe('<ListBoxSearch />', () => {
|
||||
expect(type.props.value).toBe('no matches generated by this string');
|
||||
});
|
||||
|
||||
test('should call `cancel` on `Escape`', async () => {
|
||||
test('should call `cancel` on `Escape` and stopPropagation', async () => {
|
||||
const testRenderer = testRender(model);
|
||||
const testInstance = testRenderer.root;
|
||||
const type = testInstance.findByType(OutlinedInput);
|
||||
@@ -216,12 +222,34 @@ describe('<ListBoxSearch />', () => {
|
||||
await act(async () => {
|
||||
await type.props.onKeyDown({ ...keyEventDefaults, key: 'Escape' });
|
||||
});
|
||||
// expect(selections.isActive).toHaveBeenCalledTimes(1);
|
||||
expect(selections.cancel).toHaveBeenCalledTimes(1);
|
||||
expect(model.abortListObjectSearch).not.toHaveBeenCalled();
|
||||
|
||||
expect(selections.cancel).toHaveBeenCalled();
|
||||
expect(keyEventDefaults.stopPropagation).toHaveBeenCalled();
|
||||
expect(type.props.value).toBe('foo'); // text is not reset in the test since "deactivated" is not triggered on cancel
|
||||
});
|
||||
|
||||
test('should call `cancel` on `Escape` and `return` and propagate the event', async () => {
|
||||
open = true;
|
||||
const testRenderer = create(
|
||||
<InstanceContext.Provider value={{ translator: { get: () => 'Search' } }}>
|
||||
<ListBoxSearch
|
||||
popoverOpen={open}
|
||||
selectionState={selectionState}
|
||||
styles={styles}
|
||||
selections={selections}
|
||||
model={model}
|
||||
keyboard={keyboard}
|
||||
/>
|
||||
</InstanceContext.Provider>
|
||||
);
|
||||
const testInstance = testRenderer.root;
|
||||
const type = testInstance.findByType(OutlinedInput);
|
||||
await act(async () => {
|
||||
await type.props.onKeyDown({ ...keyEventDefaults, key: 'Escape' });
|
||||
});
|
||||
expect(keyEventDefaults.stopPropagation).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should abort after performing a search and then removing the text', async () => {
|
||||
const testRenderer = testRender(model);
|
||||
const testInstance = testRenderer.root;
|
||||
|
||||
@@ -20,6 +20,18 @@ describe('keyboard navigation', () => {
|
||||
stopPropagation: jest.fn(),
|
||||
};
|
||||
|
||||
const eventCancel = {
|
||||
nativeEvent: { keyCode: KEYS.ESCAPE },
|
||||
preventDefault: jest.fn(),
|
||||
stopPropagation: jest.fn(),
|
||||
};
|
||||
|
||||
const eventConfirm = {
|
||||
nativeEvent: { keyCode: KEYS.ENTER },
|
||||
preventDefault: jest.fn(),
|
||||
stopPropagation: jest.fn(),
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
jest.resetAllMocks();
|
||||
@@ -74,24 +86,48 @@ describe('keyboard navigation', () => {
|
||||
expect(event.stopPropagation).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('confirm selections with Enter', () => {
|
||||
const eventConfirm = {
|
||||
nativeEvent: { keyCode: KEYS.ENTER },
|
||||
preventDefault: jest.fn(),
|
||||
stopPropagation: jest.fn(),
|
||||
};
|
||||
test('confirm selections with Enter and stopPropagation', () => {
|
||||
handleKeyDownForRow(eventConfirm);
|
||||
expect(actions.confirm).toHaveBeenCalledTimes(1);
|
||||
expect(actions.confirm).toHaveBeenCalled();
|
||||
expect(eventConfirm.stopPropagation).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('cancel selections with Escape', () => {
|
||||
const eventCancel = {
|
||||
nativeEvent: { keyCode: KEYS.ESCAPE },
|
||||
preventDefault: jest.fn(),
|
||||
stopPropagation: jest.fn(),
|
||||
};
|
||||
test('confirm selections with Enter and propagate the event', () => {
|
||||
isModal = undefined;
|
||||
handleKeyDownForRow = getRowsKeyboardNavigation({
|
||||
select: actions.select,
|
||||
cancel: actions.cancel,
|
||||
confirm: actions.confirm,
|
||||
setScrollPosition,
|
||||
focusListItems,
|
||||
keyboard,
|
||||
isModal,
|
||||
});
|
||||
handleKeyDownForRow(eventConfirm);
|
||||
expect(actions.confirm).toHaveBeenCalled();
|
||||
expect(eventConfirm.stopPropagation).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('cancel selections with Escape and stopPropagation', () => {
|
||||
handleKeyDownForRow(eventCancel);
|
||||
expect(actions.cancel).toHaveBeenCalledTimes(1);
|
||||
expect(actions.cancel).toHaveBeenCalled();
|
||||
expect(eventCancel.stopPropagation).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('cancel selections with Escape and propagate the event', () => {
|
||||
isModal = undefined;
|
||||
handleKeyDownForRow = getRowsKeyboardNavigation({
|
||||
select: actions.select,
|
||||
cancel: actions.cancel,
|
||||
confirm: actions.confirm,
|
||||
setScrollPosition,
|
||||
focusListItems,
|
||||
keyboard,
|
||||
isModal,
|
||||
});
|
||||
handleKeyDownForRow(eventCancel);
|
||||
expect(actions.cancel).toHaveBeenCalled();
|
||||
expect(eventCancel.stopPropagation).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('arrow up should move focus upwards', () => {
|
||||
|
||||
@@ -119,6 +119,10 @@ export default function getRowsKeyboardNavigation({
|
||||
}
|
||||
break;
|
||||
case KEYS.ESCAPE:
|
||||
if (typeof isModal === 'undefined') {
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
if (isModal()) {
|
||||
cancel();
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user