Skip to content

Commit 0eef7e7

Browse files
committed
Fix display of previous result on re-focus after close/clear button
While at it, remove the redundant `state.cursor = -1;` that `close()` already takes care of. == npm run size == JS transfer size: * Before 2224 * After 2221 (-3B)
1 parent 33a48fc commit 0eef7e7

File tree

2 files changed

+39
-3
lines changed

2 files changed

+39
-3
lines changed

test/test.js

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ QUnit.module('typesense-minibar', hooks => {
363363
assert.false(listbox.hidden, 'listbox re-opened');
364364
});
365365

366-
QUnit.test('listbox [no stale result leak on refocus]', async assert => {
366+
QUnit.test('listbox [no stale result leak after empty input]', async assert => {
367367
const form = parseHTML('<form><input type="search"></form>');
368368
const input = form.firstChild;
369369
bar = tsminibar(form);
@@ -404,6 +404,42 @@ QUnit.module('typesense-minibar', hooks => {
404404
assert.equal(listbox.querySelector('mark')?.textContent, null, 'stale snippet gone');
405405
});
406406

407+
QUnit.test('listbox [no stale result leak after close button]', async assert => {
408+
const form = parseHTML('<form><input type="search"></form>');
409+
const input = form.firstChild;
410+
bar = tsminibar(form);
411+
const listbox = form.querySelector('[role=listbox]');
412+
413+
mockFetchResponse = API_RESP_FULL_MATCH_SOMETHING;
414+
input.value = 'something';
415+
await expectRender(form, () => {
416+
simulate(input, 'input');
417+
});
418+
assert.false(listbox.hidden, 'listbox not hidden');
419+
assert.equal(listbox.querySelector('mark').outerHTML, '<mark>something</mark>', 'snippet');
420+
421+
// NOTE: close button empties programmatically without "input" event.
422+
// This means clean up of "input" event handler isn't reached.
423+
// The close button is responsible for clearing state.hits instead.
424+
mockFetchResponse = null;
425+
simulate(form.querySelector('svg.tsmb-icon-close'), 'click', { bubbles: true });
426+
assert.true(listbox.hidden, 'listbox hidden');
427+
428+
mockFetchResponse = null;
429+
simulate(document.body, 'click', { bubbles: true });
430+
assert.true(listbox.hidden, 'listbox remains hidden (document)');
431+
432+
simulate(input, 'click', { bubbles: true });
433+
assert.true(listbox.hidden, 'listbox remains hidden (refocus)');
434+
// It would be fine if render() was more lazy and left innerHTML populated
435+
// when rendering a close() that sets `state.open = false`. It only matters
436+
// that state.hits is cleared and that any future render() call will not make
437+
// the element visible, unless it also replaces innerHTML then.
438+
// But.. for simplicity, right now, we do clear the HTML unconditonally,
439+
// so let's assert that, and detect potentially unintended changes in the future.
440+
assert.equal(listbox.querySelector('mark')?.textContent, null, 'stale snippet gone');
441+
});
442+
407443
QUnit.test('listbox [arrow key cursor]', async assert => {
408444
const form = parseHTML('<form><input type="search"></form>');
409445
const input = form.firstChild;

typesense-minibar.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ globalThis.tsminibar = function tsminibar (form, dataset = form.dataset) {
4141
const query = state.query = input.value;
4242
if (!query) {
4343
state.hits = [];
44-
state.cursor = -1;
4544
return close();
4645
}
4746
const hits = await search(query);
@@ -75,8 +74,9 @@ globalThis.tsminibar = function tsminibar (form, dataset = form.dataset) {
7574
form.insertAdjacentHTML('beforeend', '<svg viewBox="0 0 12 12" width="20" height="20" aria-hidden="true" class="tsmb-icon-close" style="display: none;"><path d="M9 3L3 9M3 3L9 9"/></svg>');
7675
form.querySelector('.tsmb-icon-close').addEventListener('click', function () {
7776
input.value = '';
78-
input.focus();
77+
state.hits = [];
7978
close();
79+
input.focus();
8080
});
8181
connect();
8282

0 commit comments

Comments
 (0)