CI / build-and-test (push) Successful in 14m43s
7.3: capturedAt/source au registre + 6 adaptateurs + module provenance.ts + ?debug=1 (search-transport.mjs). 7.4: ProviderHealthService + badge source degradee. 7.6: squelettes par provider + snapshots progressifs + transport NDJSON /api/search. 8.1: ProviderAdapter unifie (search enveloppe + channelContent/channelMeta/capabilities) via getProviderAdapter + test de contrat offline.
87 lines
3.7 KiB
JavaScript
87 lines
3.7 KiB
JavaScript
/**
|
|
* Phase 8.4 — enregistreur de fixtures de contrat.
|
|
*
|
|
* Appelle les 6 adaptateurs **réels** et fige leur sortie dans
|
|
* `server/tests/fixtures/provider-suggestions.json`. Les fixtures sont donc
|
|
* générées, pas écrites à la main : elles reflètent ce que les providers
|
|
* produisent vraiment, y compris leurs champs bizarres.
|
|
*
|
|
* Réflexe : figer des objets inventés ne prouverait rien — on validerait sa
|
|
* propre imagination. Figer la sortie réelle prouve que le code d'aujourd'hui
|
|
* respecte le contrat, et le test rejoué à chaque PR détecte toute dérive.
|
|
*
|
|
* Usage : `npm run fixtures:record` (réseau requis).
|
|
* En CI : jamais exécuté. On vérifie seulement que les fixtures gelées sont
|
|
* toujours valides (`npm run test:shapes`).
|
|
*/
|
|
import fs from 'node:fs';
|
|
import os from 'node:os';
|
|
import path from 'node:path';
|
|
|
|
const OUT = path.resolve(import.meta.dirname, 'fixtures/provider-suggestions.json');
|
|
const QUERY = process.argv[2] || 'tutorial';
|
|
const LIMIT = 3;
|
|
|
|
// BASE DE DONNÉES JETABLE, définie AVANT tout import du registre.
|
|
//
|
|
// Deux raisons, toutes deux apprises à l'usage :
|
|
// 1. `search_cache` est persistant : sans base neuve, le gel rejoue des
|
|
// résultats d'un ancien gel et fige une forme PÉRIMÉE. C'est arrivé : le
|
|
// correctif de `language` PeerTube n'apparaissait pas dans les fixtures.
|
|
// 2. Le gel ne doit pas toucher `db/newtube.db` (ni y appliquer de migration).
|
|
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'newtube-record-'));
|
|
process.env.NEWTUBE_DB_FILE = path.join(tmpDir, 'record.db');
|
|
|
|
const { providerRegistry } = await import('../providers/registry.mjs');
|
|
|
|
/** Champs parasites à ne pas figer : ils changent à chaque appel et ne disent rien du contrat. */
|
|
function normalize(item) {
|
|
const out = {};
|
|
// Tri des clés : deux enregistrements successifs donnent un diff lisible.
|
|
for (const k of Object.keys(item).sort()) {
|
|
if (item[k] === undefined) continue;
|
|
out[k] = item[k];
|
|
}
|
|
return out;
|
|
}
|
|
|
|
const recorded = {
|
|
_comment: 'FIGÉ PAR `npm run fixtures:record`. Ne pas éditer à la main : régénérer.',
|
|
_contractVersion: 2,
|
|
_recordedAt: new Date().toISOString(),
|
|
_query: QUERY,
|
|
providers: {},
|
|
};
|
|
|
|
let failures = 0;
|
|
for (const id of Object.keys(providerRegistry)) {
|
|
process.stdout.write(` ${id} … `);
|
|
try {
|
|
const items = await providerRegistry[id].search(QUERY, { limit: LIMIT, page: 1, sort: 'relevance' });
|
|
const list = (Array.isArray(items) ? items : []).map(normalize);
|
|
recorded.providers[id] = list.length
|
|
? { items: list }
|
|
// Upstream indisponible au moment du gel (Rumble/Cloudflare, Odysee hors
|
|
// ligne) : on le note au lieu d'écrire un tableau vide silencieux, pour
|
|
// que la couverture manquante reste visible dans le fichier.
|
|
: { items: [], note: 'aucun résultat au moment du gel — couverture non testée pour ce provider' };
|
|
console.log(`${list.length} item(s)${list.length ? '' : ' ⚠'}`);
|
|
if (!list.length) failures++;
|
|
} catch (e) {
|
|
recorded.providers[id] = { items: [], note: `erreur au gel : ${String(e?.message || e).slice(0, 160)}` };
|
|
console.log(`ERREUR ${e?.message || e}`);
|
|
failures++;
|
|
}
|
|
}
|
|
|
|
fs.mkdirSync(path.dirname(OUT), { recursive: true });
|
|
fs.writeFileSync(OUT, `${JSON.stringify(recorded, null, 2)}\n`);
|
|
console.log(`\n→ ${path.relative(process.cwd(), OUT)}`);
|
|
if (failures) {
|
|
console.log(`\n${failures} provider(s) sans fixture exploitable : la couverture du test de contrat est partielle.`);
|
|
}
|
|
try { fs.rmSync(tmpDir, { recursive: true, force: true }); } catch {}
|
|
// Exit 1 : le gel a réussi mais est partiel (upstream HS). Le fichier est
|
|
// quand même écrit, pour que le trou de couverture soit visible dans le gel.
|
|
process.exit(failures ? 1 : 0);
|