fix(inbox): o piso da busca tira o asterisco — '**' deixa de devolver a lista inteira (#1935)

This commit is contained in:
webtecnica
2026-09-29 14:19:25 -03:00
parent 6641d26a33
commit 7f23ab825b
3 changed files with 49 additions and 2 deletions
@@ -0,0 +1,10 @@
---
impacto: nada_mudou
secao: corrigido
titulo: A busca deixa de devolver a lista inteira quando o termo tem só asteriscos
---
Digitar um termo feito só de asteriscos (duplo estrela, `* *` sem espaços) na busca da caixa de
entrada ou de contatos podia devolver tudo: o asterisco não era tratado como separador e virava
curinga no `or=`, equivalente a buscar sem critério. Agora o piso da busca o ignora — um termo só
de asteriscos não vai ao banco.
+10 -2
View File
@@ -80,8 +80,16 @@ export function normalizarTermoDeBusca(bruto: string): string {
* O `replace` NO PISO não muda o termo que vai ao banco — ele só decide se vale
* consultar. O parêntese que sobra (ex. um telefone `(15) 99259-4261`) continua
* vindo atrás dele e segue funcionando, como os controles abaixo provam.
*
* O ASTERISCO entra aqui pela mesma porta do parêntese (#1935): a pessoa pode
* digitar `*` (por exemplo `s*` pensando em curinga de nome). `normalizarTermoDeBusca`
* não colapsa `*` (não é separador), então `"**"` passa o piso; e `termoSeguroParaOr`
* NÃO escapa `*` — no `or=` do PostgREST, `*` vira `%`, e `**` vira `%%`: a lista
* inteira de volta, o mesmo defeito que o piso veio consertar. Tirá-lo do piso é
* seguro porque um `*` SEM homem no termo não significa nada para a busca — ele
* só ia ao banco para virar curinga e casar tudo.
*/
export function buscaValeConsulta(bruto: string): boolean {
const semParenteses = bruto.replace(/[()]/g, " ");
return normalizarTermoDeBusca(semParenteses).length >= PISO_DA_BUSCA;
const semLixo = bruto.replace(/[()*]/g, " ");
return normalizarTermoDeBusca(semLixo).length >= PISO_DA_BUSCA;
}
@@ -130,3 +130,32 @@ describe("termo de busca não devolve a lista inteira pelo parêntese (#1895)",
expect(buscaValeConsulta("(15) 99259")).toBe(true);
});
});
/**
* O asterisco (#1935): a lista inteira de volta por quem digita curinga.
*
* Medido na main: `buscaValeConsulta("**") === true` porque `normalizarTermoDeBusca`
* não colapsa `*` (não é separador), então `"**"` vira 2 caracteres e passa o piso;
* `termoSeguroParaOr` NÃO escapa `*`, e no `or=` do PostgREST `*` vira `%` — `**`
* casa quase tudo. É o mesmo defeito do parêntese, pela porta do usuário que digita
* `*` pensando em curinga.
*
* A régua tira o `*` ANTES de medir o piso, junto do parêntese. Se alguém remover
* o `*` do `replace`, estes casos ficam VERMELHOS (a sabotagem da #1935 prevê isso).
*/
describe("termo de busca não devolve a lista inteira pelo asterisco (#1935)", () => {
it("'**' NÃO vale consulta", () => {
expect(buscaValeConsulta("**")).toBe(false);
});
it("asterisco com conteúdo mínimo por baixo não vale", () => {
expect(buscaValeConsulta("s*")).toBe(false);
expect(buscaValeConsulta("*")).toBe(false);
});
it("CONTROLE: nome com conteúdo real continua valendo", () => {
// Sem estes, uma implementação que recusasse qualquer termo passaria.
expect(buscaValeConsulta("sabrina")).toBe(true);
expect(buscaValeConsulta("paulo jr")).toBe(true);
});
});