import { Given, Then, When } from "@badeball/cypress-cucumber-preprocessor"; // Mocks the API via cy.intercept — this job doesn't run a live backend (see // .github/workflows/ci.yml); apps/api's own Mocha suite covers real API // behavior against a real database (see test/sources.test.ts). // // "the sources reference list has options"/"the household's enabled // sources are empty" resolve from cypress/support/step_definitions/ (the // preprocessor's step-lookup is *not* global across cypress/e2e/ — only a // feature's own same-named file/directory plus that shared folder are // searched, see its error message when a step isn't found). recipes.ts // sits directly in cypress/e2e/ (not that shared folder), so its own // "the disliked ingredients list is empty"/"the recipe catalog // contains"/"recipe 2's detail is available" are scoped to recipes.feature // only — this file redeclares its own minimal equivalents rather than // relocating shared infra, the same "each spec's own self-contained // fixtures" precedent recipes.cy.ts already sets alongside recipes.ts. Given("the disliked ingredients list is empty", () => { cy.intercept("GET", "**/profile/disliked-ingredients", { statusCode: 200, body: [] }); }); Given("the recipe catalog contains nothing", () => { cy.intercept("GET", /\/recipes\?/, { statusCode: 200, body: [] }); }); Given("recipe 2's detail is available", () => { cy.intercept("GET", "**/recipes/2", { statusCode: 200, body: { id: 2, name: "Omelette", description: null, picture: null, portions: 2, authorId: 1, visibility: "PERSONAL", allergens: [], diets: [], isFavorite: false, ingredients: [], steps: [ { id: 1, description: "Cuire à la poêle.", picture: null, order: 1, techSteps: [{ techStep: { id: 1, key: "cook" }, start: 0, end: 5 }], }, ], }, }); }); Given("the household has enabled TheMealDB", () => { cy.intercept("GET", "**/house/current/sources", { statusCode: 200, body: [1] }); }); Given("browsing TheMealDB returns some items", () => { cy.intercept("GET", "**/sources/theMealDb/browse*", { statusCode: 200, body: { items: [ { externalId: "52795", title: "Chicken Handi", picture: null, url: "https://www.themealdb.com/meal/52795", alreadyImported: true, recipeId: 2, }, { externalId: "9999", title: "Fish Pie", picture: null, url: "https://www.themealdb.com/meal/9999", alreadyImported: false, recipeId: null, }, ], nextCursor: null, }, }); }); Given("previewing TheMealDB item {string} is available", (externalId: string) => { cy.intercept("GET", `**/sources/theMealDb/preview/${externalId}`, { statusCode: 200, body: { sourceKey: "theMealDb", externalId, name: "Fish Pie", description: null, picture: null, portions: 4, sourceUrl: "https://www.themealdb.com/meal/9999", ingredients: [ { rawText: "1 onion", quantity: 1, ingredient: { id: 1, key: "onion", icon: "VEGETABLE", category: "freshProduce", subcategory: "vegetables", reproducible: false, allergens: [], diets: [], }, unit: null, }, { rawText: "some mystery paste", quantity: null, ingredient: null, unit: null }, ], steps: [ { description: "Cuire à la poêle.", picture: null, techSteps: [{ techStep: { id: 1, key: "cook" }, start: 0, end: 5 }], }, ], }, }); }); Then("I should see the source item {string}", (title: string) => { cy.contains(".recipe-table__name", title).should("be.visible"); }); When("I click the source item {string}", (title: string) => { cy.contains(".recipe-table__name", title).click(); }); Then("the source item {string} should be marked as already imported", (title: string) => { cy.contains("tr", title).find(".source-item-table__imported-badge").should("be.visible"); }); // Browsing a source (outside of adding-to-planning, `RecipePickerDialog`'s // own scenarios in planning.ts) never imports anything — the only action // this preview offers is a discreet way out to the item's own page. Then("I should see a discreet link to the item's original page", () => { cy.get(".recipe-detail-panel__source-link").should("be.visible"); });