diff --git a/lib/features/popup-menu/PopupMenuComponent.js b/lib/features/popup-menu/PopupMenuComponent.js index e91d66d3b..03ca10c60 100644 --- a/lib/features/popup-menu/PopupMenuComponent.js +++ b/lib/features/popup-menu/PopupMenuComponent.js @@ -79,7 +79,7 @@ export default function PopupMenuComponent(props) { return originalEntries; } - if (!value) { + if (!value.trim()) { return originalEntries.filter(({ rank = 0 }) => rank >= 0); } diff --git a/lib/features/search-pad/SearchPad.js b/lib/features/search-pad/SearchPad.js index 94d235c71..4979d03bf 100644 --- a/lib/features/search-pad/SearchPad.js +++ b/lib/features/search-pad/SearchPad.js @@ -181,7 +181,7 @@ SearchPad.prototype._search = function(pattern) { this._clearResults(); // do not search on empty query - if (!pattern || pattern === '') { + if (!pattern.trim()) { return; } diff --git a/lib/features/search/search.js b/lib/features/search/search.js index 3b9964eb2..9d78959a7 100644 --- a/lib/features/search/search.js +++ b/lib/features/search/search.js @@ -36,6 +36,12 @@ export default function search(items, pattern, options) { keys } = options; + pattern = pattern.trim().toLowerCase(); + + if (!pattern) { + throw new Error(' must not be empty'); + } + const words = pattern.trim().toLowerCase().split(/\s+/); return items.flatMap((item) => { diff --git a/test/spec/features/popup-menu/PopupMenuSpec.js b/test/spec/features/popup-menu/PopupMenuSpec.js index 45b0c585d..dd26f57cc 100755 --- a/test/spec/features/popup-menu/PopupMenuSpec.js +++ b/test/spec/features/popup-menu/PopupMenuSpec.js @@ -1531,6 +1531,25 @@ describe('features/popup-menu', function() { })); + it('should handle whitespace only search', inject(async function(popupMenu) { + + // given + popupMenu.registerProvider('test-menu', testMenuProvider); + popupMenu.open({}, 'test-menu', { x: 100, y: 100 }, { search: true }); + + // when + await triggerSearch(' '); + + // then + await waitFor(() => { + const shownEntries = queryPopupAll('.entry'); + + // just ignores it + expect(shownEntries).to.have.length(5); + }); + })); + + describe('ranking', function() { it('should hide rank < 0 items', inject(async function(popupMenu) { diff --git a/test/spec/features/search-pad/SearchPadSpec.js b/test/spec/features/search-pad/SearchPadSpec.js index 9abc5e0f8..015bad3fb 100644 --- a/test/spec/features/search-pad/SearchPadSpec.js +++ b/test/spec/features/search-pad/SearchPadSpec.js @@ -450,6 +450,19 @@ describe('features/search-pad', function() { })); + it('should ignore whitespace only', inject(function(canvas) { + + // given + var find = sinon.spy(searchProvider, 'find'); + + // when + typeText(input_node, ' '); + + // then + expect(find).callCount(0); + })); + + it('should search per key stroke', inject(function(canvas) { // given diff --git a/test/spec/features/search/searchSpec.js b/test/spec/features/search/searchSpec.js index 166581455..f09f046b4 100644 --- a/test/spec/features/search/searchSpec.js +++ b/test/spec/features/search/searchSpec.js @@ -475,6 +475,22 @@ describe('features/search', function() { expect(results).to.have.length(1); })); + + it('should error on whitespace pattern', inject(function(search) { + + // given + const fn = () => { + search([], ' ', { + keys: [ + 'title' + ] + }); + }; + + // then + expect(fn).to.throw(/ must not be empty/); + })); + });