#!/usr/bin/env node /** * classify-tests.mjs — bucket every test file into exactly one category (no * double-counting) and sum test cases. "Swap-family" uses the founder's * definition: claim (BCH→MBA) + redeem (MBA→BCH) + redeem+claim-new (MBA→other). * Run: node scripts/classify-tests.mjs */ import { readFileSync } from 'node:fs'; import { execSync } from 'node:child_process'; const files = execSync('find test -name "*.test.ts"', { encoding: 'utf8' }).trim().split('\n'); const countCases = (src) => (src.match(/(^|\s)(it|test)\s*\(/gm) || []).length; // path-substring → bucket (first match wins; order matters) const RULES = [ // --- SWAP-FAMILY (exchange: claim / redeem / redeem+claim-new) --- ['wallet/swap-all', 'swap'], ['wallet/swap', 'swap'], ['wallet/redeem-all', 'swap'], ['wallet/redeem', 'swap'], ['regtest/redeem', 'swap'], ['regtest/swap', 'swap'], ['wallet/claim', 'swap'], ['descfee-claim', 'swap'], ['regtest/claim', 'swap'], ['regtest/escalation', 'swap'], ['wallet/market', 'swap'], ['wallet/sweep-tokens', 'swap'], ['wallet/shell', 'swap'], // --- ORACLE / USDm peg (oracle-priced mint, peg-independent redeem) --- ['oracle/', 'oracle'], ['usdm', 'oracle'], ['eurm', 'oracle'], ['pegstate', 'oracle'], // --- VERIFY / security --- ['verify/', 'verify'], ['dra-verify', 'verify'], ['regtest/verify', 'verify'], ['esc-fee-verify', 'verify'], // --- REGISTRY / persistence --- ['registry-sqlite', 'registry'], ['token/registry', 'registry'], ['registry/server', 'registry'], ['token/sync', 'registry'], ['wallet/register', 'registry'], // --- TAXONOMY / encoding / denomination --- ['assetClass', 'taxonomy'], ['token/classify', 'taxonomy'], ['token/portable', 'taxonomy'], ['tokenId', 'taxonomy'], ['default-denomination', 'taxonomy'], ['denomination', 'taxonomy'], ['tier.test', 'taxonomy'], // --- WEB / onramp --- ['web/api', 'web-onramp'], ['web/onramp-route', 'web-onramp'], ['onramp/', 'web-onramp'], // --- CRYPTO --- ['crypto/', 'crypto'], // --- GOVERNANCE / other instruments --- ['voting-canonical', 'governance'], // --- WALLET-INFRA (transfers, genesis, display, cli, etc. — NOT swaps) --- ['wallet/genesis', 'infra'], ['wallet/send-tier-a', 'infra'], ['wallet/send', 'infra'], ['wallet/display', 'infra'], ['wallet/import', 'infra'], ['wallet/cashback', 'infra'], ['wallet/runtime', 'infra'], ['wallet/wallet', 'infra'], ['cli/', 'infra'], ['connect/proposer', 'infra'], ['regtest/errors', 'infra'], ]; const LABEL = { swap: 'SWAP-family (claim/redeem/redeem+claim)', oracle: 'Oracle / USDm peg (oracle-mint, peg-indep. redeem)', verify: 'Verify / security', registry: 'Registry / persistence', taxonomy: 'Taxonomy / encoding / denomination', 'web-onramp': 'Web API / on-ramp', crypto: 'Crypto', governance: 'Governance (voting)', infra: 'Wallet infra (send, genesis, display, CLI)' }; const buckets = {}; const unmatched = []; let total = 0; for (const f of files) { const n = countCases(readFileSync(f, 'utf8')); total += n; const rule = RULES.find(([sub]) => f.includes(sub)); if (!rule) { unmatched.push(`${n} ${f}`); buckets['unmatched'] = (buckets['unmatched'] || 0) + n; continue; } buckets[rule[1]] = (buckets[rule[1]] || 0) + n; } console.log(`TOTAL test cases: ${total} (across ${files.length} files)\n`); const rows = Object.entries(buckets).sort((a, b) => b[1] - a[1]); for (const [k, v] of rows) console.log(` ${String(v).padStart(4)} ${(((v/total)*100).toFixed(1)+'%').padStart(6)} ${LABEL[k] || k}`); const swap = buckets.swap || 0; console.log(`\n SWAP-family = ${swap}/${total} = ${((swap/total)*100).toFixed(1)}% · non-swap = ${total-swap} = ${(((total-swap)/total)*100).toFixed(1)}%`); if (unmatched.length) { console.log('\n unmatched files (bucket "other"):'); unmatched.forEach((u) => console.log(' ' + u)); } console.log('\n NOTE: wallet/shell is the tx-builder shared by claim/redeem/swap AND send — counted in SWAP but ~mixed.');