Files
OmniRoute/tests/unit/db/encryption-error-handling.test.mjs
Diego Rodrigues de Sa e Souza 0757503eae perf(test): tsx/esm loader + tsx 4.23 + órfãos recuperados + CI via npm scripts (plano testes+CI, Pacote 1) (#6214)
* perf(test): tsx/esm loader, tsx 4.23 bump, orphan tests recovered, CI runs npm scripts

Pacote 1 (quick wins) do plano mestre testes+CI:

- Swap --import tsx -> --import tsx/esm on the 19 test scripts: the repo is pure
  ESM and the CJS hook costs ~1.3s PER test process (2,462 processes/run).
  Measured: bootstrap 2.3s -> 1.1s; real-suite A/B (tests/unit/db, 12 files)
  22.2s -> 14.1s wall (-36%), 82/82 pass. Non-test scripts keep the full hook.
- Bump tsx ^4.22.3 -> ^4.23.0 (fix for privatenumber/tsx#809 startup regression;
  helps module resolution on big graphs — hook cost unchanged, honest note).
- Recover 22 ORPHAN test files (tests/unit/feature-triage/*.test.mjs, 53 cases,
  53/53 pass) that matched no glob and ran in NO CI job; drop the dead
  'executors' dir from the braces glob.
- Single source of truth for the unit-suite invocation: new test:unit:ci:shard
  (shard via TEST_SHARD env) called by ci.yml test-unit/node24/node26/coverage
  and quality.yml fast-unit — closing two silent drifts: CI was NOT importing
  setupPolyfill.ts, and the fast path glob OMITTED tests/unit/memory + usage.
  quality.yml TIA step + ci.yml test-integration get the tsx/esm swap only.

Validation: full unit suite 21,153 tests / 21,135 pass / 13 skip (5 fails =
known load-flake family, 10/10 green rerun isolated); vitest 237/237; smoke
db+feature-triage 135/135. Record run 2 = ci.yml workflow_dispatch on the
stacked pacote-2 branch (clean runners).

* fix(test): dashboard UI tests keep full tsx hook; recover 15 more .mjs orphans; extend discovery gate to .mjs

Follow-up do dispatch de validacao (run 28720431562), que pegou 2 problemas reais:

1. tests/unit/dashboard/** (11 arquivos, 102 casos) importam componentes React cujo
   grafo puxa @lobehub/icons — o build es/ dele faz require() interno de arquivos com
   sintaxe ESM, que so funciona com o patch CJS do tsx (sem ele: SyntaxError
   'Unexpected token export' no CI; local vira crawl de ~60s/arquivo). Esses 11
   arquivos rodam agora numa 2a invocacao com --import tsx COMPLETO (mesmo shard),
   e o resto da suite mantem tsx/esm (-50% bootstrap). Validado: 102/102.
2. check:test-discovery falhou porque ancorava textualmente os globs nos workflows —
   COLLECTORS atualizado p/ o modelo fonte-unica (ancora = nome do script
   test:unit:ci:shard nos workflows) + varredura ESTENDIDA a .test.mjs, que era o
   ponto cego que deixou os orfaos apodrecerem. A extensao revelou +15 orfaos .mjs
   (top-level + db/) alem dos 22 de feature-triage — TODOS religados via glob
   tests/unit/**/*.test.mjs (171/171 pass). Um deles (encryption-error-handling)
   codificava o contrato PRE-hardening (decrypt falho retornava ciphertext cru —
   vazamento); alinhado ao contrato shipped (null + log) com comentario.

Gate: [test-discovery] OK — 2892 arquivos, 22 collectors, 60 orfaos congelados
(divida rastreada, shrink-only).
2026-07-04 21:21:23 -03:00

44 lines
1.9 KiB
JavaScript

import { test } from "node:test";
import assert from "node:assert";
// Chave determinística p/ exercitar o caminho real de auth-tag (sem ela o decrypt
// curto-circuita no branch "no key"). Definida ANTES do import — a derivação de chave
// é cacheada lazy no primeiro uso.
process.env.STORAGE_ENCRYPTION_KEY = "unit-test-storage-encryption-key-0123456789";
const { decrypt } = await import("../../../src/lib/db/encryption.ts");
// Contrato atual (hardening): falha de decrypt → null + log, NUNCA o ciphertext cru
// (devolver o blob criptografado vazaria o dado cifrado para UI/API). Este arquivo era
// um órfão de glob (nunca rodou em CI) e codificava o contrato antigo pré-hardening —
// alinhado ao comportamento real/shipped em 2026-07 (plano mestre testes+CI, QW-c).
test("decrypt() with invalid auth tag should not crash and return null", () => {
const invalidCiphertext = "enc:v1:0000:0000:0000";
const result = decrypt(invalidCiphertext);
assert.strictEqual(result, null, "Failed auth-tag decrypt must return null (never the raw blob)");
});
test("decrypt() with malformed ciphertext should not crash and return null", () => {
const malformed = "enc:v1:invalid";
const result = decrypt(malformed);
assert.strictEqual(result, null, "Malformed encrypted value must return null");
});
test("decrypt() with null should return null", () => {
const result = decrypt(null);
assert.strictEqual(result, null, "Should return null for null input");
});
test("decrypt() with undefined should return undefined", () => {
const result = decrypt(undefined);
assert.strictEqual(result, undefined, "Should return undefined for undefined input");
});
test("decrypt() with non-encrypted string should return as-is", () => {
const plaintext = "this-is-not-encrypted";
const result = decrypt(plaintext);
assert.strictEqual(result, plaintext, "Should return plaintext unchanged");
});