// Controlul negativ al probelor offline ale clientilor JavaScript si Python pentru rutele 1.7.0 (identityVerify / identity_verify, // complianceCheck / compliance_check): fiecare paznic se strica intr-o COPIE a SDK-ului (depozitul nu se atinge), proba ruleaza pe copie // si proba numita TREBUIE sa pice. Trei stari: ROSU cum trebuia, CONTROL CAZUT (proba a ramas verde), STRICAT (ancora nu apare exact o // data, sau probele nu au ajuns la rezumat). La urma, copia neatinsa trebuie sa fie verde (martorul). // node sdk/test/control-negativ-js-python.mjs -> 0 toate rosii si martorul verde, 1 altfel import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; import { spawnSync } from 'node:child_process'; import { fileURLToPath } from 'node:url'; const SDK = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); const PLANTARI = [ // [nume, fisier, vechi, nou, limbaj, proba (fragment din numele ei)] ['JS: complianceCheck pe ruta identitatii', 'index.mjs', "complianceCheck(request) { return this._req('POST', '/compliance/check', { body: request }); }", "complianceCheck(request) { return this._req('POST', '/identity/verify', { body: request }); }", 'js', '1.7.0: identityVerify si complianceCheck'], ['JS: identityVerify trimite o cerere schimbata', 'index.mjs', "identityVerify(request) { return this._req('POST', '/identity/verify', { body: request }); }", "identityVerify(request) { return this._req('POST', '/identity/verify', { body: { ...request, maxAgeSeconds: 3600 } }); }", 'js', '1.7.0: identityVerify si complianceCheck'], ['Python: compliance_check pe ruta identitatii', 'python/aere_cloud/__init__.py', 'return self._req("POST", "/compliance/check", request)', 'return self._req("POST", "/identity/verify", request)', 'py', 'identity_verify si compliance_check'], ['Python: identity_verify trimite o cerere schimbata', 'python/aere_cloud/__init__.py', 'return self._req("POST", "/identity/verify", request)', 'return self._req("POST", "/identity/verify", {**request, "maxAgeSeconds": 3600})', 'py', 'identity_verify si compliance_check'], // 1.8.0: chitanta trimisa pe ruta riscului; verificarea cu cererea schimbata ['JS: paymentsReceipt pe ruta riscului', 'index.mjs', "paymentsReceipt(request) { return this._req('POST', '/payments/receipt', { body: request }); }", "paymentsReceipt(request) { return this._req('POST', '/payments/risk', { body: request }); }", 'js', 'paymentsRisk, paymentsReceipt si paymentsVerify'], ['JS: paymentsVerify trimite o cerere schimbata', 'index.mjs', "paymentsVerify(request) { return this._req('POST', '/payments/verify', { body: request }); }", "paymentsVerify(request) { return this._req('POST', '/payments/verify', { body: { ...request, policy: {} } }); }", 'js', 'paymentsRisk, paymentsReceipt si paymentsVerify'], ['Python: payments_receipt pe ruta riscului', 'python/aere_cloud/__init__.py', 'return self._req("POST", "/payments/receipt", request)', 'return self._req("POST", "/payments/risk", request)', 'py', 'payments_risk, payments_receipt si payments_verify'], ['Python: payments_verify trimite o cerere schimbata', 'python/aere_cloud/__init__.py', 'return self._req("POST", "/payments/verify", request)', 'return self._req("POST", "/payments/verify", {**request, "policy": {}})', 'py', 'payments_risk, payments_receipt si payments_verify'], ]; function copie() { const d = fs.mkdtempSync(path.join(os.tmpdir(), 'aere-sdk-cn-')); for (const f of ['index.mjs', 'package.json', 'test/sdk.test.mjs', 'python/aere_cloud/__init__.py', 'python/test_aere_cloud.py', 'python/pyproject.toml']) { fs.mkdirSync(path.dirname(path.join(d, f)), { recursive: true }); fs.copyFileSync(path.join(SDK, f), path.join(d, f)); } return d; } function ruleaza(d, limbaj) { const r = limbaj === 'js' ? spawnSync(process.execPath, ['test/sdk.test.mjs'], { cwd: d, encoding: 'utf8', env: { ...process.env, AERE_CHEIE: '' } }) : spawnSync(process.platform === 'win32' ? 'python' : 'python3', ['test_aere_cloud.py'], { cwd: path.join(d, 'python'), encoding: 'utf8', env: { ...process.env, AERE_KEY: '' } }); const out = (r.stdout || '') + (r.stderr || ''); // JS: ' teste trecute' si randuri ' ESEC '; Python: ' treceri, esecuri' si randuri ' PICA ' return { out, rulat: /\d+ (teste trecute|treceri)/.test(out), rosii: out.split('\n').filter((l) => /^\s*(ESEC|PICA)\b/.test(l)) }; } let rele = 0; for (const limbaj of ['js', 'py']) { const d = copie(); const m = ruleaza(d, limbaj); fs.rmSync(d, { recursive: true, force: true }); if (m.rulat && !m.rosii.length) console.log(` martor ${limbaj}: copia neatinsa verde`); else { rele++; console.log(` STRICAT martorul ${limbaj} nu e verde (${m.rosii.length} rosii, rulat ${m.rulat})`); } } for (const [nume, fisier, vechi, nou, limbaj, tinta] of PLANTARI) { const d = copie(); try { const f = path.join(d, fisier); const t = fs.readFileSync(f, 'utf8'); if (t.split(vechi).length !== 2) { rele++; console.log(` STRICAT ${nume}: ancora apare de ${t.split(vechi).length - 1} ori`); continue; } fs.writeFileSync(f, t.replace(vechi, nou)); const r = ruleaza(d, limbaj); if (!r.rulat) { rele++; console.log(` STRICAT ${nume}: probele nu au ajuns la rezumat`); continue; } if (r.rosii.some((l) => l.includes(tinta))) console.log(` ROSU cum trebuia ${nume}`); else { rele++; console.log(` CONTROL CAZUT ${nume}: '${tinta}' a ramas verde`); } } finally { fs.rmSync(d, { recursive: true, force: true }); } } console.log(rele ? `CONTROL NEGATIV: ${rele} probleme` : `CONTROL NEGATIV TRECUT (${PLANTARI.length} din ${PLANTARI.length} rosii, martorii verzi)`); process.exitCode = rele ? 1 : 0;