batchCooking/apps/api/test/sources/sources-index.test.ts
Nicolas 2251aa93d7
Some checks failed
CI / lint (push) Successful in 4m8s
CI / build (push) Successful in 3m5s
CI / intent-service-test (push) Successful in 6m16s
CI / e2e (push) Successful in 8m15s
CI / test (push) Failing after 15m27s
feat(sources): ajoute ohmonbento.com comme source de recettes importable
6e adaptateur, le plus simple des scrapés : `fetchDetail`/`parse`
délèguent tels quels à `jsonLdRecipeAdapter` — une page recette porte un
`Recipe` WP Recipe Maker dans un `@graph` Yoast, déjà géré nativement par
`findRecipeNode`. `list()` : recherche WordPress `GET /?s={query}&paged={N}`
— **même URL que la requête soit vide (tout le catalogue) ou non**, aucun
branchement (contrairement à `750g.ts`). Scrape de cartes
`<div class="entry-thumb"><a href="/<slug>/"><img alt src>` — image dans
`src` (pas de lazy-load `data-src` ici), `href` relatif résolu contre
l'origine. Une page au-delà de la dernière renvoie une vraie 404 → fin de
liste propre (comme `marmiton.ts`). `rekeySourceError` dupliqué localement.

Enregistré dans `registerAllRecipeSources()`.

Tests : `ohmonbento.test.ts` (`stubFetchHtml`, pas de base) — scrape des
cartes, 404 = fin de liste, URL `/?s=` identique pour requête vide, query
+ page dans `/?s={q}&paged={n}`, erreurs re-labellisées `ohMonBento`,
`parse` sur un `@graph` Yoast + WPRM (`recipeYield` en tableau géré).
Vérifié localement, 9/9. + `sources-index.test.ts` couvre
l'enregistrement.

Docs : section `ohmonbento.ts` dans `backend-architecture.md`.

Closes #40

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-06 01:30:44 +02:00

79 lines
3 KiB
TypeScript

import { expect } from "chai";
import {
clearRecipeSources,
getRecipeSource,
listRecipeSources,
} from "../../src/lib/recipe-sources/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 Marmiton into the shared registry", () => {
registerAllRecipeSources();
const marmiton = getRecipeSource("marmiton");
expect(marmiton).to.not.be.undefined;
expect(marmiton?.name).to.equal("Marmiton");
expect(listRecipeSources().map((adapter) => adapter.key)).to.include("marmiton");
});
it("registers 750g into the shared registry", () => {
registerAllRecipeSources();
const sevenFiftyG = getRecipeSource("750g");
expect(sevenFiftyG).to.not.be.undefined;
expect(sevenFiftyG?.name).to.equal("750g");
expect(listRecipeSources().map((adapter) => adapter.key)).to.include("750g");
});
it("registers Manger Bouger into the shared registry", () => {
registerAllRecipeSources();
const mangerBouger = getRecipeSource("mangerBouger");
expect(mangerBouger).to.not.be.undefined;
expect(mangerBouger?.name).to.equal("Manger Bouger");
expect(listRecipeSources().map((adapter) => adapter.key)).to.include("mangerBouger");
});
it("registers Quitoque into the shared registry", () => {
registerAllRecipeSources();
const quitoque = getRecipeSource("quitoque");
expect(quitoque).to.not.be.undefined;
expect(quitoque?.name).to.equal("Quitoque");
expect(listRecipeSources().map((adapter) => adapter.key)).to.include("quitoque");
});
it("registers Oh mon Bento into the shared registry", () => {
registerAllRecipeSources();
const ohMonBento = getRecipeSource("ohMonBento");
expect(ohMonBento).to.not.be.undefined;
expect(ohMonBento?.name).to.equal("Oh mon Bento");
expect(listRecipeSources().map((adapter) => adapter.key)).to.include("ohMonBento");
});
it("does not register the generic JSON-LD adapter — it's not a household-toggleable source in its own right", () => {
registerAllRecipeSources();
expect(getRecipeSource("jsonLdRecipe")).to.be.undefined;
expect(listRecipeSources().map((adapter) => adapter.key)).to.not.include("jsonLdRecipe");
});
});