Files
insomnia/packages/insomnia-data/common-src/search.test.ts
Bingbing 8a1dc1ef62 perf: rewrite command palette search to eliminate UI freezes and stale results (#10257)
* perf: rewrite command palette search to eliminate UI freezes and stale results

Problems fixed:
- clientLoader blocked navigation on every palette open, freezing the UI during
  full sequential DB scan
- no AbortController: stale searches could overwrite newer results mid-type
- no debounce: every keystroke triggered a full DB traversal immediately
- React Aria's default contains filter re-filtered server-side fuzzy results,
  silently dropping valid matches and making fuzzy work redundant
- no warm baseline: palette started blank until the entire load completed

Changes:
- move fuzzyMatch/fuzzyMatchAll → insomnia-data/common-src/search.ts (shared,
  testable in node)
- move search logic → insomnia-data/node-src/services/helpers/command-search.ts
  - per-request AbortController cancellation via abort(requestId)
  - recursion depth guard (max 20) on request group traversal
  - safeParent() replaces non-null assertions, safe against orphaned documents
- add CommandSearchResult type in insomnia-data/src/command-search-types.ts
- add useCommandSearch hook: 250ms debounce + abort on filter change + warm
  baseline on mount
- add defaultFilter={() => true} to ComboBox, delegating all filtering to the
  service
- delete routes/commands.tsx

* fix

* fix
2026-07-17 01:07:38 +00:00

70 lines
2.0 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { fuzzyMatch, fuzzyMatchAll } from './search';
describe('fuzzyMatch()', () => {
it('can get a positive fuzzy match on a single field', () => {
expect(fuzzyMatch('test', 'testing')).toEqual({
score: -3,
indexes: [0, 1, 2, 3],
target: 'testing',
});
expect(fuzzyMatch('tst', 'testing')).toEqual({
score: -3004,
indexes: [0, 2, 3],
target: 'testing',
});
});
it('can get a negative fuzzy match on a single field', () => {
// @ts-expect-error
expect(fuzzyMatch('foo')).toBeNull();
expect(fuzzyMatch('foo', 'bar')).toBeNull();
});
});
describe('fuzzyMatchAll()', () => {
it('can get a positive fuzzy match on multiple fields', () => {
// @ts-expect-error
expect(fuzzyMatchAll('', [undefined])).toEqual(null);
expect(fuzzyMatchAll('', ['testing'])).toEqual(null);
expect(fuzzyMatchAll(' ', ['testing'])).toEqual(null);
expect(fuzzyMatchAll('test', ['testing', 'foo'])).toEqual({
score: -3,
indexes: [0, 1, 2, 3],
target: 'testing foo',
});
expect(
fuzzyMatchAll('test foo', ['testing', 'foo'], {
splitSpace: true,
}),
).toEqual({
score: 0,
indexes: [0, 1, 2, 3, 0, 1, 2],
target: 'testing foo',
});
expect(fuzzyMatchAll('tst', ['testing'])).toEqual({
score: -3004,
indexes: [0, 2, 3],
target: 'testing',
});
expect(
fuzzyMatch('tst this ou', 'testing this out', {
splitSpace: true,
loose: true,
}),
).toEqual({
score: -12.8,
indexes: [0, 2, 3, 8, 9, 10, 11, 13, 14],
target: 'testing this out',
});
});
it('can get a negative fuzzy match on multiple fields', () => {
// @ts-expect-error
expect(fuzzyMatchAll('foo', [undefined])).toEqual(null);
expect(fuzzyMatchAll('foo', ['bar'])).toEqual(null);
expect(fuzzyMatchAll('wrong this ou', ['testing', 'this', 'out'])).toEqual(null);
});
});