fix(recipes): la source générique JSON-LD n'apparaît plus comme source

jsonLdRecipeAdapter était enregistré (et donc synchronisé comme Source
sélectionnable par un foyer) au même titre que theMealDbAdapter — mais
c'est une structure générique de parsing schema.org destinée à être
déclinée par site web scrappé, pas une source qu'on peut raisonnablement
« activer » ou « faire confiance » en tant que telle (aucun catalogue à
parcourir : list() renvoie toujours vide).

registerAllRecipeSources() ne l'enregistre donc plus — elle reste
utilisable directement (un futur adapter par site l'utiliserait en
interne, ou un futur flux « importer depuis une URL » l'appellerait
directement), simplement plus comme Source autonome du registre.

Corrige aussi le mock Cypress qui prétendait « mirrorer ce qui est
vraiment seedé » avec cette même source — remplacé par un second exemple
clairement illustratif (Marmiton), qui ne correspond à aucun adapter réel.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Nicolas 2026-08-20 15:10:51 +02:00
parent 9e5e950873
commit 73206c442b
4 changed files with 31 additions and 20 deletions

View file

@ -1,16 +1,17 @@
import { registerRecipeSource } from "../lib/recipe-source-registry.js"; import { registerRecipeSource } from "../lib/recipe-source-registry.js";
import { jsonLdRecipeAdapter } from "./json-ld-recipe.js";
import { theMealDbAdapter } from "./the-meal-db.js"; import { theMealDbAdapter } from "./the-meal-db.js";
/** /**
* Registers every concrete `RecipeSourceAdapter` this app ships with into * Registers every concrete, *browsable* `RecipeSourceAdapter` this app
* the shared in-memory registry (`recipe-source-registry.ts`) currently * ships with into the shared in-memory registry
* `theMealDbAdapter` and `jsonLdRecipeAdapter`. Called once, explicitly, by * (`recipe-source-registry.ts`) currently just `theMealDbAdapter`.
* the two real entry points that need the registry populated: * Called once, explicitly, by the two real entry points that need the
* registry populated:
* *
* - `server.ts` the running API process, before it starts listening. * - `server.ts` the running API process, before it starts listening.
* - `prisma/seed.ts` so `syncRecipeSources` has something to mirror into * - `prisma/seed.ts` so `syncRecipeSources` has something to mirror into
* the `sources` table. * the `sources` table (`Source`, household-toggleable see
* `HouseSource`).
* *
* Deliberately **not** imported by `app.ts`: `createApp()` is what every * Deliberately **not** imported by `app.ts`: `createApp()` is what every
* test file gets via supertest, and registering a real adapter there would * test file gets via supertest, and registering a real adapter there would
@ -19,8 +20,16 @@ import { theMealDbAdapter } from "./the-meal-db.js";
* `clearRecipeSources()` clears it out) instead of each test's own * `clearRecipeSources()` clears it out) instead of each test's own
* explicit setup. Tests that need a source in the registry register their * explicit setup. Tests that need a source in the registry register their
* own throwaway fake instead (see e.g. `test/recipe-source-sync.test.ts`). * own throwaway fake instead (see e.g. `test/recipe-source-sync.test.ts`).
*
* `jsonLdRecipeAdapter` (json-ld-recipe.ts) is deliberately **not**
* registered here it's a generic schema.org-JSON-LD parser meant to be
* specialized per scraped website (a concrete adapter for a specific site
* would use it internally), not a household-toggleable `Source` in its own
* right: nobody can meaningfully "trust" or "enable" a generic parsing
* mechanism the way they can a named website. Until real per-site adapters
* exist, it's called directly (e.g. a future "import from a pasted URL"
* flow), never through this registry.
*/ */
export function registerAllRecipeSources(): void { export function registerAllRecipeSources(): void {
registerRecipeSource(theMealDbAdapter); registerRecipeSource(theMealDbAdapter);
registerRecipeSource(jsonLdRecipeAdapter);
} }

View file

@ -25,12 +25,10 @@ describe("registerAllRecipeSources", () => {
expect(listRecipeSources().map((adapter) => adapter.key)).to.include("theMealDb"); expect(listRecipeSources().map((adapter) => adapter.key)).to.include("theMealDb");
}); });
it("registers the generic JSON-LD source into the shared registry", () => { it("does not register the generic JSON-LD adapter — it's not a household-toggleable source in its own right", () => {
registerAllRecipeSources(); registerAllRecipeSources();
const jsonLd = getRecipeSource("jsonLdRecipe"); expect(getRecipeSource("jsonLdRecipe")).to.be.undefined;
expect(jsonLd).to.not.be.undefined; expect(listRecipeSources().map((adapter) => adapter.key)).to.not.include("jsonLdRecipe");
expect(jsonLd?.official).to.equal(false);
expect(listRecipeSources().map((adapter) => adapter.key)).to.include("jsonLdRecipe");
}); });
}); });

View file

@ -65,7 +65,7 @@ Feature: Household settings
Then I should see the section "Sources disponibles" Then I should see the section "Sources disponibles"
And I should see "TheMealDB" And I should see "TheMealDB"
And I should see "Officielle" And I should see "Officielle"
And I should see "Import générique (JSON-LD)" And I should see "Marmiton"
And I should see "Non officielle" And I should see "Non officielle"
When I check the checkbox "TheMealDB" When I check the checkbox "TheMealDB"
Then the source selection update request should have been made with source id 1 Then the source selection update request should have been made with source id 1

View file

@ -40,11 +40,15 @@ Given("the sources reference list is empty", () => {
cy.intercept("GET", "**/reference/sources", { statusCode: 200, body: [] }); cy.intercept("GET", "**/reference/sources", { statusCode: 200, body: [] });
}); });
// Mirrors what's actually seeded (`reference-seed-data.ts`'s // The real first entry (`theMealDb`) mirrors what's actually seeded
// `registerAllRecipeSources`/`syncRecipeSources`) — one official API source // (`reference-seed-data.ts`'s `registerAllRecipeSources`/
// with an icon, one unofficial scraper without one — so the sources step // `syncRecipeSources`); the second is illustrative only — a future
// (onboarding and `/parametres/foyer` alike) has something real to show // per-site scraper adapter, not tied to any real one that exists yet (the
// instead of self-skipping. // generic `jsonLdRecipeAdapter` is deliberately never registered as a
// household-toggleable source in its own right — see `sources/index.ts`).
// Two entries so the sources step (onboarding and `/parametres/foyer`
// alike) has more than one thing to show/select, instead of self-skipping
// or exercising only a single-item list.
Given("the sources reference list has options", () => { Given("the sources reference list has options", () => {
cy.intercept("GET", "**/reference/sources", { cy.intercept("GET", "**/reference/sources", {
statusCode: 200, statusCode: 200,
@ -58,8 +62,8 @@ Given("the sources reference list has options", () => {
}, },
{ {
id: 2, id: 2,
key: "jsonLdRecipe", key: "marmiton",
name: "Import générique (JSON-LD)", name: "Marmiton",
official: false, official: false,
iconUrl: null, iconUrl: null,
}, },