Deuxième adaptateur concret, cette fois générique plutôt que lié à un site précis : la plupart des sites de recettes embarquent des données structurées JSON-LD (schema.org/Recipe) pour le SEO/Google Rich Results — un seul adaptateur peut donc couvrir une grande partie des sites, sans scraper le DOM site par site. - apps/api/src/sources/json-ld-recipe.ts : official: false (on lit du HTML arbitraire, pas une API dédiée maintenue par l'éditeur), pas de catalogue à parcourir (list() renvoie toujours vide) — fetchDetail() prend directement une URL comme externalId, prête pour un futur flux "importer depuis une URL". - Extraction JSON-LD par regex (pas de nouvelle dépendance — un tag <script> ne contient jamais de HTML imbriqué, donc pas besoin d'un vrai parseur DOM), tolérante aux blocs multiples et aux JSON malformés (ignorés plutôt que de faire échouer toute la page). Gère les variantes réelles de schema.org : @type en tableau, @graph, recipeInstructions en string/HowToStep[]/HowToSection imbriquées, image en string/ImageObject/tableau, recipeYield en nombre/texte/ tableau. Vérifié contre une vraie page (bbcgoodfood.com, HTML téléchargé + fetch live) : nom, description, image, portions, 8 ingrédients et 2 étapes correctement extraits de bout en bout. 26 nouveaux tests (tous avec fetch stubbé, aucun appel réseau réel dans la suite automatisée). 221 tests passent au total. Build et lint propres. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
36 lines
1.3 KiB
TypeScript
36 lines
1.3 KiB
TypeScript
import { expect } from "chai";
|
|
import {
|
|
clearRecipeSources,
|
|
getRecipeSource,
|
|
listRecipeSources,
|
|
} from "../src/lib/recipe-source-registry.js";
|
|
import { registerAllRecipeSources } from "../src/sources/index.js";
|
|
|
|
// Not exercised by any other test file — `registerAllRecipeSources` is
|
|
// deliberately never imported by `app.ts` (see its own doc comment), so
|
|
// nothing else in the suite triggers it. Registers/clears explicitly here
|
|
// rather than relying on module-load order, so this test's outcome doesn't
|
|
// depend on which other test file Mocha happens to load first.
|
|
describe("registerAllRecipeSources", () => {
|
|
afterEach(() => {
|
|
clearRecipeSources();
|
|
});
|
|
|
|
it("registers TheMealDB into the shared registry", () => {
|
|
registerAllRecipeSources();
|
|
|
|
const theMealDb = getRecipeSource("theMealDb");
|
|
expect(theMealDb).to.not.be.undefined;
|
|
expect(theMealDb?.name).to.equal("TheMealDB");
|
|
expect(listRecipeSources().map((adapter) => adapter.key)).to.include("theMealDb");
|
|
});
|
|
|
|
it("registers the generic JSON-LD source into the shared registry", () => {
|
|
registerAllRecipeSources();
|
|
|
|
const jsonLd = getRecipeSource("jsonLdRecipe");
|
|
expect(jsonLd).to.not.be.undefined;
|
|
expect(jsonLd?.official).to.equal(false);
|
|
expect(listRecipeSources().map((adapter) => adapter.key)).to.include("jsonLdRecipe");
|
|
});
|
|
});
|