Files
EVCS/tools/fetch-snapshot-fixture.mjs
Tallagrand Thierry d1efeac44c R3: suite de tests golden — 16 scénarios, bloquante avant push
- tests/golden/run.mjs : chaîne complète des 5 nodes (code réel) en sandbox vm,
  horloge simulée par scénario, snapshot HA réel comme fixture.
- 16 scénarios attendus figés après revue : nuit HC (P7), solaire, abondance P6,
  provocation P3, gardes SOC, force_grid/force_charge, stop, overload.
- n8n-push.mjs exécute la suite avant tout PUT du workflow EVCS :
  golden rouge = push refusé (--skip-golden en échappatoire consciente).
- Validé par mutation : P7 cassé volontairement -> 2 échecs détectés + push bloqué.
- tools/fetch-snapshot-fixture.mjs : recapture d'un snapshot production.
2026-08-07 19:16:03 +02:00

51 lines
2.1 KiB
JavaScript

#!/usr/bin/env node
// Capture un snapshot HA RÉEL depuis une exécution n8n récente du workflow EVCS
// → tests/golden/fixture-snapshot.json (base des scénarios golden).
// Usage: node tools/fetch-snapshot-fixture.mjs [executionId]
import fs from 'fs';
import os from 'os';
import path from 'path';
const WORKFLOW_ID = 'ATswvGfG4KJUls0K';
const SNAPSHOT_NODE = 'HA Snapshot EVCS Surplus Controller V2.2';
const OUT = 'tests/golden/fixture-snapshot.json';
function loadApiConfig() {
const cfgPath = path.join(os.homedir(), '.config/opencode/opencode.json');
const cfg = JSON.parse(fs.readFileSync(cfgPath, 'utf8'));
const env = cfg?.mcp?.['n8n-mcp']?.environment || {};
return {
url: (env.N8N_API_URL || '').replace(/\/api\/v1\/?$/, ''),
key: env.N8N_API_KEY
};
}
const { url, key } = loadApiConfig();
const headers = { 'X-N8N-API-KEY': key };
let execId = process.argv[2];
if (!execId) {
const res = await fetch(`${url}/api/v1/executions?workflowId=${WORKFLOW_ID}&status=success&limit=1`, { headers });
const list = await res.json();
execId = list.data?.[0]?.id;
if (!execId) { console.error('Aucune exécution trouvée'); process.exit(1); }
}
const res = await fetch(`${url}/api/v1/executions/${execId}?includeData=true`, { headers });
if (!res.ok) { console.error(`GET exécution ${execId}: ${res.status}`); process.exit(1); }
const exec = await res.json();
const runData = exec.data?.resultData?.runData;
if (!runData?.[SNAPSHOT_NODE]) {
console.error(`Node "${SNAPSHOT_NODE}" absent des données. Nodes dispo: ${Object.keys(runData || {}).join(', ')}`);
process.exit(1);
}
const items = runData[SNAPSHOT_NODE][0]?.data?.main?.[0];
if (!items?.length) { console.error('Pas de données de sortie sur le node snapshot'); process.exit(1); }
const snapshot = items[0].json;
fs.mkdirSync(path.dirname(OUT), { recursive: true });
fs.writeFileSync(OUT, JSON.stringify(snapshot, null, 2) + '\n');
console.log(`Fixture écrite: ${OUT} (exécution ${execId}, ${Object.keys(snapshot).length} champs)`);
console.log(`Champs: ${Object.keys(snapshot).sort().join(', ')}`);