diff --git a/packages/@n8n/utils/src/search/sublimeSearch.test.ts b/packages/@n8n/utils/src/search/sublimeSearch.test.ts index f725e26e7ee..8cadfdca292 100644 --- a/packages/@n8n/utils/src/search/sublimeSearch.test.ts +++ b/packages/@n8n/utils/src/search/sublimeSearch.test.ts @@ -1,22 +1,36 @@ +import { reRankSearchResults } from './reRankSearchResults'; import topLevel from './snapshots/toplevel.snapshot.json'; import { sublimeSearch } from './sublimeSearch'; +// Mirrors packages/frontend/editor-ui/data/node-popularity.json scaled by the factor +// applied in useViewStacks.ts. Only the nodes asserted below are included. +const popularity: Record = { + /* eslint-disable @typescript-eslint/naming-convention */ + 'n8n-nodes-base.set': 0.959 * 100, + 'n8n-nodes-base.editImage': 0.617 * 100, + '@n8n/n8n-nodes-langchain.agent': 0.975 * 100, + /* eslint-enable @typescript-eslint/naming-convention */ +}; + describe('sublimeSearch', () => { describe('search finds specific matches first', () => { - // Note that this only tests the order of the specified matches - // Further results may appear after the listed ones + // Mirrors the production pipeline in useViewStacks.ts: + // sublimeSearch(query, items) → reRankSearchResults(results, { popularity }) + // Note that this only tests the order of the specified matches. + // Further results may appear after the listed ones. const testCases: Array<[string, string[]]> = [ ['set', ['Edit Fields (Set)']], + ['edit', ['Edit Fields (Set)']], ['agent', ['AI Agent', 'Magento 2']], ]; test.each(testCases)( 'should return at least "$expectedOrder" for filter "$filter"', (filter, expectedOrder) => { - // These match the weights in the production use case const results = sublimeSearch(filter, topLevel); + const reRanked = reRankSearchResults(results, { popularity }); - const resultNames = results.map((result) => result.item.properties.displayName); + const resultNames = reRanked.map((result) => result.item.properties.displayName); expectedOrder.forEach((expectedName, index) => { expect(resultNames[index]).toBe(expectedName); }); diff --git a/packages/@n8n/utils/src/search/sublimeSearch.ts b/packages/@n8n/utils/src/search/sublimeSearch.ts index 85167440f57..adc59bf429d 100644 --- a/packages/@n8n/utils/src/search/sublimeSearch.ts +++ b/packages/@n8n/utils/src/search/sublimeSearch.ts @@ -10,7 +10,7 @@ const FIRST_LETTER_BONUS = 15; // bonus if the first letter is matched const LEADING_LETTER_PENALTY = -20; // penalty applied for every letter in str before the first match const MAX_LEADING_LETTER_PENALTY = -200; // maximum penalty for leading letters -const UNMATCHED_LETTER_PENALTY = -5; +const UNMATCHED_LETTER_PENALTY = -2.5; export const DEFAULT_KEYS = [ { key: 'properties.displayName', weight: 1.3 },