falsegreen-js (JavaScript / TypeScript)¶
O scanner determinístico para JS/TS. Uma varredura estática via TypeScript compiler API, sem
execução de código, agnóstica ao runner entre Jest, Vitest, Mocha+Chai, Jasmine, AVA, node:test,
Cypress, Playwright e Testing Library. Cobre .js, .jsx, .ts, .tsx, .mjs, .cjs, .mts,
.cts.
- Repositório: github.com/vinicq/falsegreen-js
- Catálogo: códigos JavaScript / TypeScript
Install¶
Use¶
npx falsegreen-js src # scan
npx falsegreen-js --format json|sarif|junit # output shape (matches the Python sibling)
npx falsegreen-js --baseline .falsegreen-baseline.json
npx falsegreen-js --config-audit # jest/vitest config for project-level false-green
O relatório JSON carrega riskGroup e oracleRegistryVersion: os códigos são classificados em
grupos de risco fechados, e o registro de oráculos (sync-fail / promise / runner-registered /
value-only) é versionado, de modo que a detecção de assíncrono é baseada em princípios em vez de
casada por string.
First finding¶
Salve um teste cuja asserção nunca roda:
// demo.test.ts
import { add } from "./add";
it("adds", () => {
expect(add(2, 2)); // sem matcher - isso não asserta nada
});
Rode o scanner sobre ele:
Ele reporta:
demo.test.ts:5 [JS2] expect() with no matcher - the assertion never runs
level: unit fix: add a matcher, e.g. .toBe(4)
Summary: 1 high, 0 low.
Reading a finding¶
Cada linha carrega os mesmos campos:
demo.test.ts:5- o arquivo e a linha que disparou o achado.[JS2]- o código do catálogo.JS2é oexpect()sem matcher. Cada código está explicado no catálogo JS/TS.level: unit- em qual nível da pirâmide de testes o arquivo está, lido a partir dos imports do arquivo.fix:- uma dica de uma linha. Aqui: adicione um matcher para a asserção realmente rodar.
--format json|sarif|junit dá um relatório legível por máquina; o SARIF sobe
para o GitHub code scanning e os achados aparecem direto no pull request.
Complete usage and configuration¶
O guia inicial acima é o caminho de cinco minutos. Esta seção é a referência completa: cada canal de instalação, cada formato de saída, cada chave de configuração, o contrato de código de saída e a integração com CI. Espelha o que o README do projeto documenta.
Install channels¶
Node 18 ou mais novo. O scanner lê .js, .jsx, .ts, .tsx, .mjs, .cjs, .mts, .cts.
npm install -D falsegreen-js # dependência de desenvolvimento do projeto
npm install -g falsegreen-js # instalação global
npx falsegreen-js . # roda a última versão do npm sem instalar
node dist/cli.js . # roda de um checkout clonado
Agnóstico de runner: o vocabulário de asserção e teste cobre Jest, Vitest, Mocha + Chai, Jasmine,
AVA, node:test, tap, Cypress, Playwright, Testing Library e Vue Test Utils, então um teste Mocha
ou AVA não é confundido com um que nunca checa nada.
Invocation¶
npx falsegreen-js # escaneia o cwd
npx falsegreen-js src test # escaneia caminhos
npx falsegreen-js --staged # só os arquivos de teste no stage do git (pre-commit)
Cada achado é reportado com seu nível na pirâmide (unit / integration / e2e, lido dos imports do arquivo) e uma dica de correção de uma linha; o resumo separa os achados por nível e lista as correções mais comuns.
Output formats¶
--format text|json|sarif|junit seleciona o formato do relatório (padrão text). --json
continua como alias de --format json. Eles casam com o irmão Python conceito a
conceito, então um pipeline pode trocar um scanner pelo outro.
npx falsegreen-js . --json # JSON legível por máquina
npx falsegreen-js . --format sarif # SARIF 2.1.0
npx falsegreen-js . --format junit # JUnit XML
npx falsegreen-js . --output report.json # grava em arquivo
npx falsegreen-js . --output .falsegreen/ # grava report.<ext> num diretório
sarifemite SARIF 2.1.0: uma regra por código presente, um resultado por achado,errorpara ALTO,warningpara BAIXO,notepara desligado. As tags do resultado carregam o julgamento (J1-J6), o grupo de risco (risk:effectiveness...) e o nível. Suba para o GitHub code scanning para ver os achados inline no PR.junitemite JUnit XML: achados ALTO viram<failure>, o resto vira<skipped>, então um reporter de CI os mostra como suíte falhando.
O relatório JSON ainda carrega riskGroup e oracleRegistryVersion: os códigos são classificados
em grupos de risco fechados, e o registro de oráculos (sync-fail / promise / runner-registered /
value-only) é versionado para que a detecção async seja principiada, não casada por string.
--output aceita arquivo ou diretório; mantenha o diretório de saída no gitignore.
Configuration¶
Desabilitar / habilitar códigos (CLI).
npx falsegreen-js --disable C7,JS3 # desliga códigos específicos
npx falsegreen-js --enable D8,M2 # reativa códigos desligados/opcionais na severidade do catálogo
npx falsegreen-js --diagnostics # inclui o grupo de manutenibilidade D*/M* como avisos
--enable liga um código desligado por padrão na severidade do catálogo; não pode subir um código
acima do catálogo. Um código passado a --enable e --disable ao mesmo tempo continua desligado,
--disable vence.
Grupo de diagnóstico (desligado por padrão). Estes não são false-green, então só avisam: D1
assertion roulette, D3 assert duplicado, D4 casos de each só por índice, D6 console.* num
teste, D7 teste anônimo, D8 número mágico, M2 corpo de teste longo. Ligue todos com
--diagnostics, ou por código via severity na config.
Supressão inline. Um comentário na linha do achado silencia um achado justificado:
Arquivo de config do projeto. falsegreen.json, .falsegreenrc.json, ou uma chave
"falsegreen" no package.json:
Precedência, da maior para a menor: --disable na CLI, --enable na CLI, disable / severity
da config, padrão do catálogo.
Auditoria de config. --config-audit é um modo separado. Em vez de escanear arquivos de teste,
lê a config de Jest / Vitest (campo jest do package.json, jest.config.*, vitest.config.*) e
reporta as formas de nível de projeto pelas quais uma suíte fica verde por configuração:
PL10-passWithNoTestspassa numa execução vazia ou filtrada até o nada.PL7- semcoverageThreshold/coverage.thresholds.PL8-bailinterrompe a execução cedo.
Baseline (catraca). Adote o scanner numa base grande sem corrigir todo achado legado de uma vez:
npx falsegreen-js --write-baseline # registra os achados atuais em .falsegreen-baseline.json, exit 0
npx falsegreen-js --baseline # reporta e falha só nos achados que não estão no baseline
--baseline [PATH] e --write-baseline [PATH] usam .falsegreen-baseline.json por padrão. A
identidade de um achado é um fingerprint de conteúdo (sha1 de caminho relativo + código + detalhe,
sem número de linha), então sobrevive a deslocamentos de linha não relacionados. Comite o baseline
e deixe o CI bloquear só nos achados novos.
Exit codes¶
| Código | Significado |
|---|---|
0 |
limpo, nenhum achado que afete o gate |
10 |
só achados de baixa confiança |
20 |
ao menos um achado de alta confiança |
Bloqueie o commit no 20.
CI integration¶
GitHub Actions. Um job que falha no exit 20:
name: falsegreen-js
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: "20" }
- run: npx falsegreen-js . # exit 20 falha o job
Upload de SARIF para o GitHub code scanning. Emita SARIF e passe para a action do CodeQL para que os achados apareçam inline no pull request:
- run: npx falsegreen-js . --format sarif --output falsegreen.sarif
continue-on-error: true
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: falsegreen.sarif
Hook de pre-commit. Rode o scan dos arquivos em stage como hook com --staged:
- repo: local
hooks:
- id: falsegreen-js
name: falsegreen-js
entry: npx falsegreen-js --staged
language: system
pass_filenames: false
types_or: [javascript, ts, tsx, jsx]
Para a camada que nenhum scan estático alcança (um teste verde falha quando o código está errado?), rode um teste de mutação como o Stryker. O falsegreen-js é o pré-filtro barato em todo commit; os casos semânticos (intenção, correção do oráculo) são a falsegreen-skill.
What it covers¶
Detalhe completo por código no catálogo JS/TS.
| Grupo | Códigos | Efeito |
|---|---|---|
| Compartilhado com Python (F1-F6) | C2, C2b, C5, C6, C7, C8, C9, C16, C18, C20, C21, C23, C37, C44, CC |
ALTO bloqueia, BAIXO avisa |
| Específico de JavaScript | JS1-JS9, JS11, JS13, JS15, JS17, JS18, JS21, JS22 |
idem |
| Diagnóstico / acoplamento (F8) | D1, D3, D4, D6, D7, D8, M2 |
opcional |
Projeto / CI (--config-audit) |
PL10 (--passWithNoTests), PL7 (limiar de cobertura), PL8 (bail) |
lê a config do jest/vitest |
What it does not cover, and why¶
Fora de escopo (o eixo errado)¶
O mesmo limite do resto da família: fragilidade/falso-vermelho, higiene, lentidão, design, nomenclatura, duplicação, runtime. Veja cobertura vs a literatura.
Códigos JS deixados de fora de propósito¶
| Código | O que sinalizaria | Por que não |
|---|---|---|
| JS10 | qualquer condicional no corpo do teste | amplo demais; jest/no-conditional-in-test (ESLint) já cobre. No máximo, diagnóstico |
| JS12 | uma promise com expect não retornada/aguardada |
absorvido por JS7 |
| JS14 | um snapshot gigante | higiene (F8), não false-green |
| JS16 | teste assíncrono sem a guarda expect.assertions(n) |
a ausência de uma guarda não é um smell; sinalizá-la tem taxa de falso-positivo altíssima |
| JS19 | toBe sobre um literal de objeto/array (era toEqual) |
isto é falso-VERMELHO (uma checagem de identidade que falha em código correto): o eixo oposto |
| JS20 | uma Promise comparada sem resolves/rejects |
saber que o sujeito é uma Promise exige informação de tipo; falso positivo alto |
Não aplicável a partir do Python¶
Códigos específicos do pytest não têm análogo em JS: as regras de coleta (família C4), os
códigos de binding/escopo de pytest.raises, os códigos de capsys/os.environ. Estão ausentes
de propósito, não esquecidos.
Além do scanner¶
A fatia semântica (intenção, correção do oráculo) é a falsegreen-skill; o runtime (mutação com Stryker) fica fora de banda. Veja escopo e honestidade.