mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 06:43:06 +00:00
Papel communicator com nav própria e gate speechCatalog; acervo em /campanha/comunicacao/acervo com busca normalizada (destaque no trecho), filtros de ano/tema/alcance/fase/município/duração em URL canônica e paginação por discurso via speech.searchText (GIN trgm + backfill). Detalhe com player nativo no trecho, transcrição clicável, baixar/abrir fonte e fallback sem VOD. Resolve o débito do C153 (Sollinha fora da vertical) e corrige o parser de keywords oficiais no dono. Closes #956
76 lines
2.8 KiB
TypeScript
76 lines
2.8 KiB
TypeScript
// @vitest-environment node
|
|
|
|
import { describe, expect, it } from 'vitest'
|
|
|
|
import {
|
|
buildHighlightedExcerpt,
|
|
findHighlightRanges,
|
|
matchesSearchTerms,
|
|
splitHighlightedParts,
|
|
} from '@/lib/speechHighlight'
|
|
|
|
const highlighted = (text: string, query: string): string[] =>
|
|
splitHighlightedParts(text, query)
|
|
.filter((part) => part.highlighted)
|
|
.map((part) => part.text)
|
|
|
|
describe('findHighlightRanges', () => {
|
|
it('maps an accent-free query back to the accented original spelling', () => {
|
|
const text = 'A defesa do SUS e da saúde pública'
|
|
expect(findHighlightRanges(text, 'saude')).toEqual([{ start: 21, end: 26 }])
|
|
expect(highlighted(text, 'saude')).toEqual(['saúde'])
|
|
})
|
|
|
|
it('finds every term of a multi-word query, accent-insensitively', () => {
|
|
const text = 'O Governo retomou a Farmácia Popular na Bahia'
|
|
expect(highlighted(text, 'farmacia popular')).toEqual(['Farmácia', 'Popular'])
|
|
expect(highlighted(text, 'FARMÁCIA')).toEqual(['Farmácia'])
|
|
})
|
|
|
|
it('merges overlapping occurrences', () => {
|
|
expect(findHighlightRanges('banana', 'ana')).toEqual([{ start: 1, end: 6 }])
|
|
})
|
|
|
|
it('handles whitespace and punctuation around the match', () => {
|
|
const text = ' saúde,\n educação '
|
|
expect(highlighted(text, 'saude educacao')).toEqual(['saúde', 'educação'])
|
|
})
|
|
|
|
it('returns nothing for an empty query or a miss', () => {
|
|
expect(findHighlightRanges('texto', '')).toEqual([])
|
|
expect(findHighlightRanges('texto', 'inexistente')).toEqual([])
|
|
})
|
|
})
|
|
|
|
describe('matchesSearchTerms', () => {
|
|
it('requires every term, in any order', () => {
|
|
expect(matchesSearchTerms('A defesa do SUS e da saúde', 'saude sus')).toBe(true)
|
|
expect(matchesSearchTerms('A defesa do SUS', 'saude educacao')).toBe(false)
|
|
expect(matchesSearchTerms('A defesa do SUS', '')).toBe(false)
|
|
})
|
|
})
|
|
|
|
describe('buildHighlightedExcerpt', () => {
|
|
it('windows around the first match and flags truncation', () => {
|
|
const text = `${'a'.repeat(300)} saúde ${'b'.repeat(300)}`
|
|
const excerpt = buildHighlightedExcerpt(text, 'saude', { radius: 20 })
|
|
|
|
expect(excerpt.truncatedStart).toBe(true)
|
|
expect(excerpt.truncatedEnd).toBe(true)
|
|
const parts = excerpt.parts
|
|
expect(parts.some((part) => part.highlighted && part.text === 'saúde')).toBe(true)
|
|
})
|
|
|
|
it('falls back to the text start without highlights when nothing matches', () => {
|
|
const excerpt = buildHighlightedExcerpt('Uma fala sem o termo buscado', 'inexistente', {
|
|
radius: 10,
|
|
})
|
|
expect(excerpt.parts.every((part) => !part.highlighted)).toBe(true)
|
|
expect(excerpt.truncatedStart).toBe(false)
|
|
expect(excerpt.truncatedEnd).toBe(true)
|
|
})
|
|
|
|
it('returns empty parts for empty text', () => {
|
|
expect(buildHighlightedExcerpt(' ', 'saude').parts).toEqual([])
|
|
})
|
|
})
|