diff --git a/README.md b/README.md index ba79d2f..ed70de1 100644 --- a/README.md +++ b/README.md @@ -52,8 +52,11 @@ recipeScraper("some.recipe.url").then(recipe => { - https://www.food.com/ - https://www.foodandwine.com/ - https://www.foodnetwork.com/ +- https://gimmedelicious.com/ - http://www.gimmesomeoven.com/ +- https://julieblanner.com/ - https://www.kitchenstories.com/ +- https://www.melskitchencafe.com/ - https://www.minimalistbaker.com/ - https://www.myrecipes.com/ - https://www.nomnompaleo.com/ @@ -64,7 +67,9 @@ recipeScraper("some.recipe.url").then(recipe => { - https://www.simplyrecipes.com/ - https://smittenkitchen.com/ - https://thepioneerwoman.com/ +- https://www.tasteofhome.com/ - https://tastesbetterfromscratch.com/ +- https://www.theblackpeppercorn.com/ - https://therealfoodrds.com/ - https://www.thespruceeats.com/ - https://whatsgabycooking.com/ diff --git a/scrapers/gimmedelicious.js b/scrapers/gimmedelicious.js new file mode 100644 index 0000000..7cb777c --- /dev/null +++ b/scrapers/gimmedelicious.js @@ -0,0 +1,74 @@ +const request = require("request"); +const cheerio = require("cheerio"); + +const RecipeSchema = require("../helpers/recipe-schema"); + +const gimmedelicious = url => { + const Recipe = new RecipeSchema(); + return new Promise((resolve, reject) => { + if (!url.includes("gimmedelicious.com/")) { + reject(new Error("url provided must include 'gimmedelicious.com/'")); + } else { + request(url, (error, response, html) => { + if (!error && response.statusCode === 200) { + const $ = cheerio.load(html); + + Recipe.image = $("meta[property='og:image']").attr("content"); + Recipe.tags = ( + $("meta[name='keywords']").attr("content") || "" + ).split(","); + Recipe.name = $(".wprm-recipe-name") + .text() + .trim(); + + $(".wprm-recipe-ingredients > .wprm-recipe-ingredient").each( + (i, el) => { + Recipe.ingredients.push( + $(el) + .text() + .replace(/▢/g, "") + ); + } + ); + + $(".wprm-recipe-instruction-text").each((i, el) => { + Recipe.instructions.push( + $(el) + .remove("img") + .text() + .trim() + ); + }); + + Recipe.time.prep = + $(".wprm-recipe-prep_time-minutes").text() + + " " + + $(".wprm-recipe-prep_timeunit-minutes").text(); + Recipe.time.cook = + $(".wprm-recipe-cook_time-minutes").text() + + " " + + $(".wprm-recipe-cook_timeunit-minutes").text(); + Recipe.time.total = + $(".wprm-recipe-total_time-minutes").text() + + " " + + $(".wprm-recipe-total_timeunit-minutes").text(); + Recipe.servings = $(".wprm-recipe-servings").text(); + + if ( + !Recipe.name || + !Recipe.ingredients.length || + !Recipe.instructions.length + ) { + reject(new Error("No recipe found on page")); + } else { + resolve(Recipe); + } + } else { + reject(new Error("No recipe found on page")); + } + }); + } + }); +}; + +module.exports = gimmedelicious; diff --git a/scrapers/index.js b/scrapers/index.js index c5d3ad8..4cc9951 100644 --- a/scrapers/index.js +++ b/scrapers/index.js @@ -19,8 +19,11 @@ const domains = { food: require("./food"), foodandwine: require("./foodandwine"), foodnetwork: require("./foodnetwork"), + gimmedelicious: require("./gimmedelicious"), gimmesomeoven: require("./gimmesomeoven"), + julieblanner: require("./julieblanner"), kitchenstories: require("./kitchenstories"), + melskitchencafe: require("./melskitchencafe"), minimalistbaker: require("./minimalistbaker"), myrecipes: require("./myrecipes"), nomnompaleo: require("./nomnompaleo"), @@ -31,6 +34,9 @@ const domains = { simplyrecipes: require("./simplyrecipes"), smittenkitchen: require("./smittenkitchen"), tastesbetterfromscratch: require("./tastesbetterfromscratch"), + tasteofhome: require("./tasteofhome"), + theblackpeppercorn: require("./theblackpeppercorn"), + therecipecritic: require("./therecipecritic"), thepioneerwoman: require("./thepioneerwoman"), therealfoodrds: require("./therealfoodrds"), thespruceeats: require("./thespruceeats"), @@ -55,4 +61,8 @@ const recipeScraper = url => { }); }; +recipeScraper( + "https://www.thespruceeats.com/grilled-squid-recipe-1808848" +).then(recipe => console.log(recipe)); + module.exports = recipeScraper; diff --git a/scrapers/julieblanner.js b/scrapers/julieblanner.js new file mode 100644 index 0000000..70a9fbd --- /dev/null +++ b/scrapers/julieblanner.js @@ -0,0 +1,72 @@ +const request = require("request"); +const cheerio = require("cheerio"); + +const RecipeSchema = require("../helpers/recipe-schema"); + +const julieblanner = url => { + const Recipe = new RecipeSchema(); + return new Promise((resolve, reject) => { + if (!url.includes("julieblanner.com/")) { + reject(new Error("url provided must include 'julieblanner.com/'")); + } else { + request(url, (error, response, html) => { + if (!error && response.statusCode === 200) { + const $ = cheerio.load(html); + + Recipe.image = $("meta[property='og:image']").attr("content"); + Recipe.name = $(".wprm-recipe-name") + .text() + .trim(); + + $(".wprm-recipe-ingredients > .wprm-recipe-ingredient").each( + (i, el) => { + Recipe.ingredients.push( + $(el) + .text() + .replace(/(\s\s+|▢)/g, " ") + .trim() + ); + } + ); + + $(".wprm-recipe-instruction-text").each((i, el) => { + Recipe.instructions.push( + $(el) + .remove("img") + .text() + .trim() + ); + }); + + Recipe.time.prep = $(".wprm-recipe-prep-time-label") + .next() + .text(); + Recipe.time.cook = $(".wprm-recipe-cook-time-label") + .next() + .text(); + Recipe.time.inactive = $(".wprm-recipe-custom-time-label") + .next() + .text(); + Recipe.time.total = $(".wprm-recipe-total-time-label") + .next() + .text(); + Recipe.servings = $(".wprm-recipe-servings").text(); + + if ( + !Recipe.name || + !Recipe.ingredients.length || + !Recipe.instructions.length + ) { + reject(new Error("No recipe found on page")); + } else { + resolve(Recipe); + } + } else { + reject(new Error("No recipe found on page")); + } + }); + } + }); +}; + +module.exports = julieblanner; diff --git a/scrapers/melskitchencafe.js b/scrapers/melskitchencafe.js new file mode 100644 index 0000000..1a2e439 --- /dev/null +++ b/scrapers/melskitchencafe.js @@ -0,0 +1,64 @@ +const request = require("request"); +const cheerio = require("cheerio"); + +const RecipeSchema = require("../helpers/recipe-schema"); + +const melskitchencafe = url => { + const Recipe = new RecipeSchema(); + return new Promise((resolve, reject) => { + if (!url.includes("melskitchencafe.com/")) { + reject(new Error("url provided must include 'melskitchencafe.com/'")); + } else { + request(url, (error, response, html) => { + if (!error && response.statusCode === 200) { + const $ = cheerio.load(html); + + const textTrim = el => el.text().trim(); + + Recipe.image = $("meta[property='og:image']").attr("content"); + Recipe.name = textTrim( + $(".wp-block-mv-recipe .mv-create-title-primary") + ); + + $("div.mv-create-ingredients ul li").each((i, el) => { + Recipe.ingredients.push(textTrim($(el))); + }); + + $("div.mv-create-instructions ol li").each((i, el) => { + Recipe.instructions.push(textTrim($(el))); + }); + + Recipe.time.prep = textTrim( + $(".mv-create-time-prep .mv-create-time-format") + ); + Recipe.time.cook = textTrim( + $(".mv-create-time-active .mv-create-time-format") + ); + Recipe.time.inactive = textTrim( + $(".mv-create-time-additional .mv-create-time-format") + ); + Recipe.time.total = textTrim( + $(".mv-create-time-total .mv-create-time-format") + ); + Recipe.servings = textTrim( + $(".mv-create-time-yield .mv-create-time-format") + ); + + if ( + !Recipe.name || + !Recipe.ingredients.length || + !Recipe.instructions.length + ) { + reject(new Error("No recipe found on page")); + } else { + resolve(Recipe); + } + } else { + reject(new Error("No recipe found on page")); + } + }); + } + }); +}; + +module.exports = melskitchencafe; diff --git a/scrapers/tasteofhome.js b/scrapers/tasteofhome.js new file mode 100644 index 0000000..36fa1d5 --- /dev/null +++ b/scrapers/tasteofhome.js @@ -0,0 +1,63 @@ +const request = require("request"); +const cheerio = require("cheerio"); + +const RecipeSchema = require("../helpers/recipe-schema"); + +const tasteofhome = url => { + const Recipe = new RecipeSchema(); + return new Promise((resolve, reject) => { + if (!url.includes("tasteofhome.com/recipes/")) { + reject(new Error("url provided must include 'tasteofhome.com/recipes/'")); + } else { + request(url, (error, response, html) => { + if (!error && response.statusCode === 200) { + const $ = cheerio.load(html); + + Recipe.image = $("meta[property='og:image']").attr("content"); + Recipe.name = $("h1.recipe-title") + .text() + .trim(); + + $("meta[property='article:tag']").each((i, el) => { + Recipe.tags.push($(el).attr("content")); + }); + + $(".recipe-ingredients__list li").each((i, el) => { + Recipe.ingredients.push($(el).text()); + }); + + $(".recipe-directions__item").each((i, el) => { + Recipe.instructions.push( + $(el) + .text() + .trim() + ); + }); + + let timeStr = $(".recipe-time-yield__label-prep") + .text() + .split(/Bake:/g); + Recipe.time.prep = timeStr[0].replace("Prep:", "").trim(); + Recipe.time.cook = (timeStr[1] || "").trim(); + Recipe.servings = $(".recipe-time-yield__label-servings") + .text() + .trim(); + + if ( + !Recipe.name || + !Recipe.ingredients.length || + !Recipe.instructions.length + ) { + reject(new Error("No recipe found on page")); + } else { + resolve(Recipe); + } + } else { + reject(new Error("No recipe found on page")); + } + }); + } + }); +}; + +module.exports = tasteofhome; diff --git a/scrapers/theblackpeppercorn.js b/scrapers/theblackpeppercorn.js new file mode 100644 index 0000000..ac1c291 --- /dev/null +++ b/scrapers/theblackpeppercorn.js @@ -0,0 +1,72 @@ +const request = require("request"); +const cheerio = require("cheerio"); + +const RecipeSchema = require("../helpers/recipe-schema"); + +const theblackpeppercorn = url => { + const Recipe = new RecipeSchema(); + return new Promise((resolve, reject) => { + if (!url.includes("theblackpeppercorn.com/")) { + reject(new Error("url provided must include 'theblackpeppercorn.com/'")); + } else { + request(url, (error, response, html) => { + if (!error && response.statusCode === 200) { + const $ = cheerio.load(html); + + Recipe.image = $("meta[property='og:image']").attr("content"); + Recipe.name = $(".wprm-recipe-name") + .text() + .trim(); + + $(".wprm-recipe-ingredients > .wprm-recipe-ingredient").each( + (i, el) => { + Recipe.ingredients.push( + $(el) + .text() + .replace(/(▢)/g, "") + .replace(" ,", ",") + ); + } + ); + + $(".wprm-recipe-instruction-text").each((i, el) => { + Recipe.instructions.push( + $(el) + .remove("img") + .text() + .replace(/\s\s+/g, "") + ); + }); + + Recipe.time.prep = $(".wprm-recipe-prep-time-label") + .next() + .text(); + Recipe.time.cook = $(".wprm-recipe-cook-time-label") + .next() + .text(); + Recipe.time.inactive = $(".wprm-recipe-custom-time-label") + .next() + .text(); + Recipe.time.total = $(".wprm-recipe-total-time-label") + .next() + .text(); + Recipe.servings = $(".wprm-recipe-servings").text(); + + if ( + !Recipe.name || + !Recipe.ingredients.length || + !Recipe.instructions.length + ) { + reject(new Error("No recipe found on page")); + } else { + resolve(Recipe); + } + } else { + reject(new Error("No recipe found on page")); + } + }); + } + }); +}; + +module.exports = theblackpeppercorn; diff --git a/scrapers/therecipecritic.js b/scrapers/therecipecritic.js new file mode 100644 index 0000000..8156de7 --- /dev/null +++ b/scrapers/therecipecritic.js @@ -0,0 +1,57 @@ +const request = require("request"); +const cheerio = require("cheerio"); + +const RecipeSchema = require("../helpers/recipe-schema"); + +const therecipecritic = url => { + const Recipe = new RecipeSchema(); + return new Promise((resolve, reject) => { + if (!url.includes("therecipecritic.com/")) { + reject(new Error("url provided must include 'therecipecritic.com/'")); + } else { + request(url, (error, response, html) => { + if (!error && response.statusCode === 200) { + const $ = cheerio.load(html); + const textTrim = el => el.text().trim(); + + Recipe.image = $("meta[property='og:image']").attr("content"); + Recipe.name = textTrim($(".wprm-recipe-name")); + + $(".wprm-recipe-ingredient").each((i, el) => { + Recipe.ingredients.push(textTrim($(el)).replace(/\s\s+/g, " ")); + }); + + $(".wprm-recipe-instruction-text").each((i, el) => { + Recipe.instructions.push(textTrim($(el)).replace(/\s\s+/g, " ")); + }); + + $(".wprm-recipe-details-name").remove(); + + Recipe.time.prep = textTrim($(".wprm-recipe-prep-time-container")); + Recipe.time.cook = textTrim($(".wprm-recipe-cook-time-container")); + Recipe.time.inactive = textTrim( + $(".wprm-recipe-custom-time-container") + ); + Recipe.time.total = textTrim($(".wprm-recipe-total-time-container")); + Recipe.servings = $( + ".wprm-recipe-servings-container .wprm-recipe-servings" + ).text(); + + if ( + !Recipe.name || + !Recipe.ingredients.length || + !Recipe.instructions.length + ) { + reject(new Error("No recipe found on page")); + } else { + resolve(Recipe); + } + } else { + reject(new Error("No recipe found on page")); + } + }); + } + }); +}; + +module.exports = therecipecritic; diff --git a/scrapers/thespruceeats.js b/scrapers/thespruceeats.js index 5591213..425a2c8 100644 --- a/scrapers/thespruceeats.js +++ b/scrapers/thespruceeats.js @@ -43,12 +43,18 @@ const theSpruceEats = url => { ); }); - let metaText = $(".meta-text__data"); - Recipe.time.total = metaText.first().text(); - Recipe.time.prep = $(metaText.get(1)).text(); - Recipe.time.cook = $(metaText.get(2)).text(); - - Recipe.servings = metaText.last().text(); + let metaText = $(".meta-text").each((i, el) => { + let text = $(el).text(); + if (text.includes("Prep:")) { + Recipe.time.prep = text.replace("Prep: ", "").trim(); + } else if (text.includes("Cook: ")) { + Recipe.time.cook = text.replace("Cook:", "").trim(); + } else if (text.includes("Total: ")) { + Recipe.time.total = text.replace("Total:", "").trim(); + } else if (text.includes("Servings: ")) { + Recipe.servings = text.replace("Servings: ", "").trim(); + } + }); if ( !Recipe.name || diff --git a/scrapers/woolworths.js b/scrapers/woolworths.js index 4dd66e8..f4b3741 100644 --- a/scrapers/woolworths.js +++ b/scrapers/woolworths.js @@ -1,6 +1,4 @@ const request = require("request"); -const cheerio = require("cheerio"); - const RecipeSchema = require("../helpers/recipe-schema"); const urlRe = /\/(\d\d\d\d)\//; @@ -28,8 +26,6 @@ const woolworths = url => { }, (error, response, html) => { if (!error && response.statusCode === 200 && html) { - const $ = cheerio.load(html); - Recipe.image = html.ImageFilename; Recipe.name = html.Title.trim(); Recipe.ingredients = html.Ingredients.map(i => diff --git a/test/constants/eatingwellConstants.js b/test/constants/eatingwellConstants.js index ae1df28..742a794 100644 --- a/test/constants/eatingwellConstants.js +++ b/test/constants/eatingwellConstants.js @@ -92,6 +92,6 @@ module.exports = { }, servings: "6", image: - "https://imagesvc.meredithcorp.io/v3/mm/image?q=85&c=sc&poi=face&w=640&h=335&url=https%3A%2F%2Fcf-images.us-east-1.prod.boltdns.net%2Fv1%2Fstatic%2F5118192885001%2Fc9b189d6-367e-4c94-8b05-f805363ae20f%2Fc185934c-9360-4f85-b766-0edbbfd1a583%2F640x360%2Fmatch%2Fimage.jpg" + "https://imagesvc.meredithcorp.io/v3/mm/image?q=85&c=sc&poi=face&w=960&h=503&url=https%3A%2F%2Fstatic.onecms.io%2Fwp-content%2Fuploads%2Fsites%2F44%2F2019%2F08%2F26231112%2F3750024.jpg" } }; diff --git a/test/constants/gimmedeliciousConstants.js b/test/constants/gimmedeliciousConstants.js new file mode 100644 index 0000000..f9209d3 --- /dev/null +++ b/test/constants/gimmedeliciousConstants.js @@ -0,0 +1,44 @@ +module.exports = { + testUrl: "https://gimmedelicious.com/creamy-spinach-and-mushroom-pasta-bake", + invalidUrl: "https://gimmedelicious.com/not_real", + invalidDomainUrl: "www.invalid.com", + nonRecipeUrl: "https://gimmedelicious.com/shop/", + expectedRecipe: { + name: "Creamy Spinach and Mushroom Pasta Bake", + ingredients: [ + "12 oz pasta uncooked", + "2 tablespoons unsalted butter", + "1 small onion diced", + "1 pound mushrooms of choice thinly sliced", + "2 cloves garlic minced", + "3 cups baby spinach", + "1 teaspoon italian seasoning", + "1/2 tsp salt", + "1/4 tsp pepper", + "1 tablespoon all-purpose flour", + "1/2 cup vegetable broth or water", + "1 cup light cream or half and half", + "1/4 cup freshly grated Parmesan", + "1 cup mozzarella cheese", + "2 tablespoons chopped fresh parsley leaves" + ], + instructions: [ + "Pre-heat oven to 375F.In a large pot of boiling salted water, cook pasta according to package instructions; drain well. Set aside.", + "Melt butter in a large skillet over medium heat. onion and mushrooms, cook for 2-3 minute or until the mushrooms are soft and tender. Add garlic, spinach, italian seasoning, and salt + pepper. cook for another minute.", + "Whisk in flour until lightly browned, about 1 minute. Gradually whisk in vegetable broth and then cream, and cook, whisking constantly, until incorporated, about 1-2 minutes. Stir in parmesan just before turning off heat.", + "Pour cooked pasta into a large 13×9 baking dish. Top with spinach mushroom cream sauce. Drizzle with mozzarella cheese. Bake for 18-20 minutes or until bubbly." + ], + tags: ["mushrooms", "parmesan", "pasta", "spinach"], + time: { + prep: "5 minutes", + cook: "25 minutes", + active: "", + inactive: "", + ready: "", + total: "30 minutes" + }, + servings: "6", + image: + "https://i2.wp.com/gimmedelicious.com/wp-content/uploads/2020/12/Image-11.jpg" + } +}; diff --git a/test/constants/julieblannerConstants.js b/test/constants/julieblannerConstants.js new file mode 100644 index 0000000..1c3ec57 --- /dev/null +++ b/test/constants/julieblannerConstants.js @@ -0,0 +1,42 @@ +module.exports = { + testUrl: "https://julieblanner.com/chicken-enchiladas/", + invalidUrl: "https://julieblanner.com/not_real", + invalidDomainUrl: "www.invalid.com", + nonRecipeUrl: "https://julieblanner.com/aboutjulie", + expectedRecipe: { + name: "Chicken Enchiladas", + ingredients: [ + "2 tablespoons oil canola, vegetable, olive or butter", + "1 cup white onion chopped (about 1 small onion)", + "2 boneless, skinless chicken breasts cubed", + "1 4 ounce can diced green chilies", + "½ teaspoon salt", + "½ teaspoon pepper", + "1¼ cup enchilada sauce (homemade or 10 ounce can)", + '8 8" flour tortillas', + "3 cups cheese shredded (Mexican blend, Monterey Jack, Pepper Jack, Cheddar or Cotija)", + "1 15 ounce can black beans drained" + ], + instructions: [ + "Preheat oven to 350°F.", + "In a skillet over medium heat, add oil and onion. Sauté about 3 minutes until the onion is tender and translucent.", + "Add chicken and green chilies. Brown about 6 minutes stirring occasionally.", + "Grease 9×13 baking dish. Spread 1/4 cup enchilada sauce in bottom of dish.", + "In the center of each tortilla, layer with 1/8th of chicken leaving room at both edges. Add a spoonful of black beans and approximately 1 ounce shredded cheese.", + "Fold tortilla over the filling and tightly wrap. Place in baking dish. Top generously with remaining enchilada sauce and cheese.", + "Bake 20-25 minutes until cheese is melted and tortillas slightly crisp and brown." + ], + tags: [], + time: { + prep: "20 mins", + cook: "20 mins", + active: "", + inactive: "", + ready: "", + total: "40 mins" + }, + servings: "4", + image: + "https://julieblanner.com/wp-content/uploads/2020/09/easy-chicken-enchilada-recipe-2.jpeg" + } +}; diff --git a/test/constants/melskitchencafeConstants.js b/test/constants/melskitchencafeConstants.js new file mode 100644 index 0000000..bb3b4a5 --- /dev/null +++ b/test/constants/melskitchencafeConstants.js @@ -0,0 +1,37 @@ +module.exports = { + testUrl: + "https://www.melskitchencafe.com/bbq-pulled-pork-sandwiches-slow-cooker/", + invalidUrl: "https://www.melskitchencafe.com/not_real", + invalidDomainUrl: "www.invalid.com", + nonRecipeUrl: "https://www.melskitchencafe.com/about/", + expectedRecipe: { + name: "BBQ Pulled Pork Sandwiches", + ingredients: [ + "3 to 4 pounds boneless pork shoulder, pork butt or pork sirloin roast", + "1 teaspoon salt (I use coarse, kosher salt)", + "1/2 teaspoon black pepper (I use coarsely ground)", + "2 cups water or low-sodium chicken broth", + "1 to 2 tablespoons liquid smoke", + "2 to 3 cups BBQ sauce (plus more for serving)" + ], + instructions: [ + "Cut the pork roast into large 4-inch pieces (optional, but helps cook a bit faster and more evenly). Season the pork on all sides with salt and pepper.", + "Slow Cooker Directions: add water or broth and liquid smoke to slow cooker. Add pork. Cover and cook on low 8-10 hours or high for 5-6 hours, until the pork is fall-apart tender.", + "Pressure Cooker Directions: Decrease the water/broth to 1 cup. Add the water or broth, pork and liquid smoke to an electric pressure cooker. Secure the lid, set the valve to seal, and cook on high pressure for 55-60 minutes. Let the pressure naturally release for 10 minutes (or all the way). Quick release any remaining pressure.", + "Remove the pork from the slow cooker or pressure cooker and discard most of the remaining liquid (I leave about 1/4 cup or so). Shred the pork using a couple of forks - it should easily fall apart into pieces. Place the meat back in the slow cooker or pressure cooker. Add the BBQ sauce and heat through (or keep on warm for several hours).", + "Serve on buns with extra barbecue sauce." + ], + tags: [], + time: { + prep: "15 minutes", + cook: "8 hours", + active: "", + inactive: "", + ready: "", + total: "8 hours 15 minutes" + }, + servings: "8-12 servings", + image: + "https://www.melskitchencafe.com/wp-content/uploads/2010/08/bbq-pork-sandwich1.jpg" + } +}; diff --git a/test/constants/tasteofhomeConstants.js b/test/constants/tasteofhomeConstants.js new file mode 100644 index 0000000..7a134ae --- /dev/null +++ b/test/constants/tasteofhomeConstants.js @@ -0,0 +1,64 @@ +module.exports = { + testUrl: "https://www.tasteofhome.com/recipes/artichoke-chicken", + invalidUrl: "https://www.tasteofhome.com/recipes/not_real", + invalidDomainUrl: "www.invalid.com", + nonRecipeUrl: "https://www.tasteofhome.com/recipes/", + expectedRecipe: { + name: "Artichoke Chicken", + ingredients: [ + "8 boneless skinless chicken breast halves (4 ounces each)", + "2 tablespoons butter", + "2 jars (6 ounces each) marinated quartered artichoke hearts, drained", + "1 jar (4-1/2 ounces) whole mushrooms, drained", + "1/2 cup chopped onion", + "1/3 cup all-purpose flour", + "1-1/2 teaspoons dried rosemary, crushed", + "3/4 teaspoon salt", + "1/4 teaspoon pepper", + "2 cups chicken broth or 1 cup broth and 1 cup dry white wine", + "Hot cooked noodles", + "Minced fresh parsley" + ], + instructions: [ + "In a large skillet, brown chicken in butter. Remove chicken to an ungreased 13x9-in. baking dish. Arrange artichokes and mushrooms on top of chicken; set aside.", + "Saute onion in pan juices until crisp-tender. Combine the flour, rosemary, salt and pepper. Stir into pan until blended. Add chicken broth. Bring to a boil; cook and stir until thickened and bubbly, about 2 minutes. Spoon over chicken.", + "Bake, uncovered, at 350° until a thermometer inserted in the chicken reads 165°, about 40 minutes. Serve with noodles and sprinkle with parsley. Freeze option: Cool unbaked casserole; cover and freeze. To use, partially thaw in refrigerator overnight. Remove from refrigerator 30 minutes before baking. Preheat oven to 350°. Bake casserole as directed, increasing time as necessary to heat through and for a thermometer inserted in the chicken to read 165°." + ], + tags: [ + "13x9", + "Artichoke Hearts", + "Artichokes", + "Bakeware", + "Baking Casseroles & Savories", + "Boneless Chicken Breasts", + "Chicken", + "Cooking Style", + "Diabetic", + "Dinner", + "Easy", + "Freezer-Friendly", + "Gear", + "Health & Wellness", + "Healthy Eating", + "Ingredients", + "Meal Types", + "Meat & Poultry", + "Recipes", + "Sauteing", + "Techniques", + "Vegetables", + "Winning Recipes" + ], + time: { + prep: "15 min.", + cook: "40 min.", + active: "", + inactive: "", + ready: "", + total: "" + }, + servings: "8 servings", + image: + "https://www.tasteofhome.com/wp-content/uploads/2018/01/Artichoke-Chicken_EXPS_13X9BZ19_24_B10_04_5b-6.jpg" + } +}; diff --git a/test/constants/theblackpeppercornConstants.js b/test/constants/theblackpeppercornConstants.js new file mode 100644 index 0000000..2a9f4fb --- /dev/null +++ b/test/constants/theblackpeppercornConstants.js @@ -0,0 +1,42 @@ +module.exports = { + testUrl: "https://www.theblackpeppercorn.com/how-to-cook-a-smoked-picnic-ham", + invalidUrl: "https://www.theblackpeppercorn.com//not_real", + invalidDomainUrl: "www.invalid.com", + nonRecipeUrl: "https://www.theblackpeppercorn.com/about-me/", + expectedRecipe: { + name: "How to Cook a Picnic Ham - Smoked Pork Shoulder", + ingredients: [ + "1 smoked picnic ham (5-8 pounds)", + "2 oranges, peeled", + "1 1/2 cups brown sugar", + "1/2 cup vinegar", + "1/3 cup honey", + "2 tbsp mustard", + "1 tsp cinnamon", + "1 tsp salt", + "1/4 tsp cayenne pepper" + ], + instructions: [ + "Preheat oven to 350F", + "Place picnic ham on a large roasting pan or baking dish, fat side up. Pour 3/4 cup of water into the bottom of the baking dish.", + "Cover roasting pan with foil and bake in the oven for 1 hour. This allows the rind to be removed easily.", + "Remove the foil and peel the rind off the top of the fat cap. Cut cross check slits into the fat and about 1/2 inch into the meat of the ham.", + "Puree remaining ingredients (oranges, brown sugar, vinegar, honey, mustard, cinnamon, salt and cayenne) in a blender to make the glaze. Brush some of the glaze all over the ham, making sure to get into the slits.", + "Bake for another 2 hours, uncovered. Brush the glaze after 1 hour cooking time and then again about 30 minutes later. Bake the remaining 30 minutes.", + "Once done cooking, the fat should be starting to crisp and the glaze nicely caramelized. Let the ham rest for about 5 minutes before carving.", + "Carve the ham into nice sized serving slices. Serve with glazed carrots, potatoes, squash and more!" + ], + tags: [], + time: { + prep: "10 minutes", + cook: "3 hours", + active: "", + inactive: "", + ready: "", + total: "3 hours 10 minutes" + }, + servings: "12", + image: + "https://www.theblackpeppercorn.com/wp-content/uploads/2017/06/How-to-Cook-a-Picnic-Shoulder-Ham-hires.jpg" + } +}; diff --git a/test/constants/therecipecriticConstants.js b/test/constants/therecipecriticConstants.js new file mode 100644 index 0000000..efe37d4 --- /dev/null +++ b/test/constants/therecipecriticConstants.js @@ -0,0 +1,35 @@ +module.exports = { + testUrl: "https://therecipecritic.com/creamy-parmesan-spaghetti/", + invalidUrl: "https://therecipecritic.com/not_real", + invalidDomainUrl: "www.invalid.com", + nonRecipeUrl: "https://therecipecritic.com/food-blogger/", + expectedRecipe: { + name: "Creamy Parmesan Spaghetti", + ingredients: [ + "12 ounces spaghetti noodles", + "1 tablespoon butter", + "3 teaspoons minced garlic", + "1 cup heavy cream", + "2/3 cup shaved parmesan cheese plus more for topping", + "salt and pepper to taste" + ], + instructions: [ + "Cook spaghetti noodles according to package's instructions. Drain and set aside.", + "Add butter to a large skillet and melt over medium heat. Add garlic and stir until fragrant (2-3 minutes). Transfer spaghetti to the pan and stir to coat in the garlic butter.", + "Add heavy cream and parmesan to pan and stir until parmesan is completely melted and combined and noodles are coated.", + "Season with salt and pepper to taste, sprinkle with parmesan cheese and serve immediately." + ], + tags: [], + time: { + prep: "5 minutes", + cook: "10 minutes", + active: "", + inactive: "", + ready: "", + total: "15 minutes" + }, + servings: "4", + image: + "https://therecipecritic.com/wp-content/uploads/2016/10/garlic-parmesan-spaghetti-1sm.jpg" + } +}; diff --git a/test/gimmedelicious.test.js b/test/gimmedelicious.test.js new file mode 100644 index 0000000..0433b9d --- /dev/null +++ b/test/gimmedelicious.test.js @@ -0,0 +1,11 @@ +"use strict"; +const commonRecipeTest = require("./helpers/commonRecipeTest"); +const gimmeDelicious = require("../scrapers/gimmedelicious"); +const Constants = require("./constants/gimmedeliciousConstants"); + +commonRecipeTest( + "gimmeDelicious", + gimmeDelicious, + Constants, + "gimmedelicious.com/" +); diff --git a/test/julieblanner.test.js b/test/julieblanner.test.js new file mode 100644 index 0000000..7a8c754 --- /dev/null +++ b/test/julieblanner.test.js @@ -0,0 +1,6 @@ +"use strict"; +const commonRecipeTest = require("./helpers/commonRecipeTest"); +const julieBlanner = require("../scrapers/julieblanner"); +const Constants = require("./constants/julieblannerConstants"); + +commonRecipeTest("julieBlanner", julieBlanner, Constants, "julieblanner.com/"); diff --git a/test/melskitchencafe.test.js b/test/melskitchencafe.test.js new file mode 100644 index 0000000..3844431 --- /dev/null +++ b/test/melskitchencafe.test.js @@ -0,0 +1,11 @@ +"use strict"; +const commonRecipeTest = require("./helpers/commonRecipeTest"); +const melsKitchenCafe = require("../scrapers/melskitchencafe"); +const Constants = require("./constants/melskitchencafeConstants"); + +commonRecipeTest( + "melsKitchenCafe", + melsKitchenCafe, + Constants, + "melskitchencafe.com/" +); diff --git a/test/tasteofhome.test.js b/test/tasteofhome.test.js new file mode 100644 index 0000000..c4ff813 --- /dev/null +++ b/test/tasteofhome.test.js @@ -0,0 +1,11 @@ +"use strict"; +const commonRecipeTest = require("./helpers/commonRecipeTest"); +const tasteOfHome = require("../scrapers/tasteofhome"); +const Constants = require("./constants/tasteofhomeConstants"); + +commonRecipeTest( + "tasteOfHome", + tasteOfHome, + Constants, + "tasteofhome.com/recipes/" +); diff --git a/test/theblackpeppercorn.test.js b/test/theblackpeppercorn.test.js new file mode 100644 index 0000000..e027452 --- /dev/null +++ b/test/theblackpeppercorn.test.js @@ -0,0 +1,11 @@ +"use strict"; +const commonRecipeTest = require("./helpers/commonRecipeTest"); +const theBlackPeppercorn = require("../scrapers/theblackpeppercorn"); +const Constants = require("./constants/theblackpeppercornConstants"); + +commonRecipeTest( + "theBlackPeppercorn", + theBlackPeppercorn, + Constants, + "theblackpeppercorn.com/" +); diff --git a/test/therecipecritic.test.js b/test/therecipecritic.test.js new file mode 100644 index 0000000..d622c58 --- /dev/null +++ b/test/therecipecritic.test.js @@ -0,0 +1,11 @@ +"use strict"; +const commonRecipeTest = require("./helpers/commonRecipeTest"); +const theRecipeCritic = require("../scrapers/therecipecritic"); +const Constants = require("./constants/therecipecriticConstants"); + +commonRecipeTest( + "theRecipeCritic", + theRecipeCritic, + Constants, + "therecipecritic.com/" +);