import { describe, it, expect } from 'vitest'; import { matchFromTier, compareHits, sortHits, type RankedHit } from '@/lib/search-util'; const hit = (title: string, tier: number, score: number, type: RankedHit['type'] = 'cancer'): RankedHit => ({ type, title, tier, score }); describe('matchFromTier', () => { it('maps tiers to match labels', () => { expect(matchFromTier(0, 'cancer')).toBe('exact'); expect(matchFromTier(2, 'drug')).toBe('prefix'); expect(matchFromTier(3, 'cancer')).toBe('trigram'); expect(matchFromTier(7, 'cancer')).toBe('trigram'); }); it('calls tier 1 an identifier for code-like entities and an alias otherwise', () => { expect(matchFromTier(1, 'gene')).toBe('identifier'); expect(matchFromTier(1, 'trial')).toBe('identifier'); expect(matchFromTier(1, 'publication')).toBe('identifier'); expect(matchFromTier(1, 'variant')).toBe('identifier'); expect(matchFromTier(1, 'cancer')).toBe('alias'); expect(matchFromTier(1, 'drug')).toBe('alias'); expect(matchFromTier(1, 'source')).toBe('alias'); }); }); describe('compareHits / sortHits', () => { it('orders exact > alias/identifier > prefix > trigram regardless of score', () => { const sorted = sortHits([hit('Glioma', 3, 0.99), hit('Glioblastoma', 0, 0.2), hit('GBM', 1, 0.5), hit('Glioblastoma multiforme', 2, 0.9)]); expect(sorted.map((h) => h.title)).toEqual(['Glioblastoma', 'GBM', 'Glioblastoma multiforme', 'Glioma']); }); it('breaks tier ties by similarity, descending', () => { const sorted = sortHits([hit('B', 3, 0.3), hit('A', 3, 0.9), hit('C', 3, 0.6)]); expect(sorted.map((h) => h.title)).toEqual(['A', 'C', 'B']); }); it('breaks remaining ties alphabetically, case-insensitively', () => { const sorted = sortHits([hit('beta', 2, 0.5), hit('Alpha', 2, 0.5), hit('gamma', 2, 0.5)]); expect(sorted.map((h) => h.title)).toEqual(['Alpha', 'beta', 'gamma']); }); it('is a proper comparator (antisymmetric, zero for equal keys)', () => { const a = hit('Same', 1, 0.5, 'gene'); const b = hit('Same', 1, 0.5, 'drug'); expect(compareHits(a, b)).toBe(0); const c = hit('Other', 0, 0.1); expect(Math.sign(compareHits(a, c))).toBe(-Math.sign(compareHits(c, a))); }); it('does not mutate the input', () => { const input = [hit('b', 3, 0.1), hit('a', 0, 0.1)]; const copy = [...input]; sortHits(input); expect(input).toEqual(copy); }); });