import { describe, it, expect } from 'vitest'; import type { Observations } from '../src/core/types.js'; import { detectar } from '../src/detection/engine.js'; import { faixaDe } from '../src/detection/confidence.js'; import { montarRelatorio } from '../src/report/model.js'; function obs(patch: Partial): Observations { return { urlSolicitada: 'https://exemplo.com', urlFinal: 'https://exemplo.com/', modo: 'rapido', redirecionamentos: [], headers: {}, cookies: [], html: '', meta: {}, scriptSrc: [], linksAssets: [], globaisJs: [], avisos: [], ...patch, }; } describe('detecção do WordPress', () => { const wp = obs({ html: ' ', meta: { generator: 'WordPress 6.5.2' }, headers: { link: '; rel="https://api.w.org/"' }, scriptSrc: ['/wp-content/themes/x/app.js'], }); const deteccoes = detectar(wp); it('reconhece o WordPress com alta confiança', () => { const d = deteccoes.find((x) => x.nome === 'WordPress'); expect(d).toBeDefined(); expect(d!.confianca).toBeGreaterThanOrEqual(90); expect(d!.faixa).toBe('praticamente confirmado'); }); it('extrai a versão do meta generator', () => { expect(deteccoes.find((x) => x.nome === 'WordPress')?.versao).toBe('6.5.2'); }); it('preserva evidências de múltiplas fontes independentes', () => { const d = deteccoes.find((x) => x.nome === 'WordPress')!; expect(d.evidencias.length).toBeGreaterThan(1); expect(d.evidencias.some((e) => e.fonte === 'meta')).toBe(true); const fontes = new Set(d.evidencias.map((e) => e.fonte)); expect(fontes.size).toBeGreaterThanOrEqual(2); }); it('implica PHP e MySQL', () => { expect(deteccoes.some((x) => x.nome === 'PHP')).toBe(true); expect(deteccoes.some((x) => x.nome === 'MySQL')).toBe(true); }); }); describe('detecção do Next.js', () => { const next = obs({ html: '
/_next/static/
', headers: { 'x-powered-by': 'Next.js' }, scriptSrc: ['/_next/static/chunks/main.js'], }); const deteccoes = detectar(next); it('reconhece o Next.js e implica React', () => { expect(deteccoes.some((x) => x.nome === 'Next.js')).toBe(true); expect(deteccoes.some((x) => x.nome === 'React')).toBe(true); }); }); describe('faixas de confiança', () => { it('mapeia scores para faixas textuais', () => { expect(faixaDe(95)).toBe('praticamente confirmado'); expect(faixaDe(70)).toBe('provável'); expect(faixaDe(50)).toBe('possível'); expect(faixaDe(20)).toBe('indício fraco'); }); }); describe('bloco "não foi possível confirmar"', () => { it('lista o banco de dados quando nenhum é detectado', () => { const rep = montarRelatorio(obs({ html: '' })); expect(rep.naoDeterminado.some((i) => i.includes('banco de dados'))).toBe(true); }); it('não afirma HTTP/3 quando não anunciado', () => { const rep = montarRelatorio(obs({ protocolo: { http2: true, http3Anunciado: false } })); expect(rep.naoDeterminado.some((i) => i.toLowerCase().includes('http/3'))).toBe(true); }); });