test/detection.test.ts (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
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>): 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: '<link rel="https://api.w.org/" href="/wp-json/" /> <img src="/wp-content/uploads/logo.png">',
meta: { generator: 'WordPress 6.5.2' },
headers: { link: '<https://exemplo.com/wp-json/>; 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: '<script id="__NEXT_DATA__" type="application/json">{}</script> <div>/_next/static/</div>',
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: '<html></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);
});
});
|