test refactor first pass

This commit is contained in:
hay-kot 2021-03-29 11:48:27 -08:00
commit 747a64a7aa
49 changed files with 685 additions and 3888 deletions

97
tests/app_routes.py Normal file
View file

@ -0,0 +1,97 @@
class AppRoutes:
def __init__(self) -> None:
self.prefix = "/api"
self.users_sign_ups = "/api/users/sign-ups"
self.auth_token = "/api/auth/token"
self.auth_token_long = "/api/auth/token/long"
self.auth_refresh = "/api/auth/refresh"
self.users = "/api/users"
self.users_self = "/api/users/self"
self.groups = "/api/groups"
self.groups_self = "/api/groups/self"
self.recipes = "/api/recipes"
self.recipes_category = "/api/recipes/category"
self.recipes_tag = "/api/recipes/tag"
self.categories = "/api/categories"
self.recipes_tags = "/api/recipes/tags/"
self.recipes_create = "/api/recipes/create"
self.recipes_create_url = "/api/recipes/create-url"
self.meal_plans_all = "/api/meal-plans/all"
self.meal_plans_create = "/api/meal-plans/create"
self.meal_plans_this_week = "/api/meal-plans/this-week"
self.meal_plans_today = "/api/meal-plans/today"
self.site_settings_custom_pages = "/api/site-settings/custom-pages"
self.site_settings = "/api/site-settings"
self.site_settings_webhooks_test = "/api/site-settings/webhooks/test"
self.themes = "/api/themes"
self.themes_create = "/api/themes/create"
self.backups_available = "/api/backups/available"
self.backups_export_database = "/api/backups/export/database"
self.backups_upload = "/api/backups/upload"
self.migrations = "/api/migrations"
self.debug_version = "/api/debug/version"
self.debug_last_recipe_json = "/api/debug/last-recipe-json"
def users_sign_ups_token(self, token):
return f"{self.prefix}/users/sign-ups/{token}"
def users_id(self, id):
return f"{self.prefix}/users/{id}"
def users_id_reset_password(self, id):
return f"{self.prefix}/users/{id}/reset-password"
def users_id_image(self, id):
return f"{self.prefix}/users/{id}/image"
def users_id_password(self, id):
return f"{self.prefix}/users/{id}/password"
def groups_id(self, id):
return f"{self.prefix}/groups/{id}"
def categories_category(self, category):
return f"{self.prefix}/categories/{category}"
def recipes_tags_tag(self, tag):
return f"{self.prefix}/recipes/tags/{tag}"
def recipes_recipe_slug(self, recipe_slug):
return f"{self.prefix}/recipes/{recipe_slug}"
def recipes_recipe_slug_image(self, recipe_slug):
return f"{self.prefix}/recipes/{recipe_slug}/image"
def meal_plans_plan_id(self, plan_id):
return f"{self.prefix}/meal-plans/{plan_id}"
def meal_plans_id_shopping_list(self, id):
return f"{self.prefix}/meal-plans/{id}/shopping-list"
def site_settings_custom_pages_id(self, id):
return f"{self.prefix}/site-settings/custom-pages/{id}"
def themes_theme_name(self, theme_name):
return f"{self.prefix}/themes/{theme_name}"
def backups_file_name_download(self, file_name):
return f"{self.prefix}/backups/{file_name}/download"
def backups_file_name_import(self, file_name):
return f"{self.prefix}/backups/{file_name}/import"
def backups_file_name_delete(self, file_name):
return f"{self.prefix}/backups/{file_name}/delete"
def migrations_source_file_name_import(self, source, file_name):
return f"{self.prefix}/migrations/{source}/{file_name}/import"
def migrations_source_file_name_delete(self, source, file_name):
return f"{self.prefix}/migrations/{source}/{file_name}/delete"
def migrations_source_upload(self, source):
return f"{self.prefix}/migrations/{source}/upload"
def debug_log_num(self, num):
return f"{self.prefix}/debug/log/{num}"

View file

@ -8,11 +8,12 @@ from mealie.db.db_setup import generate_session, sql_global_init
from mealie.db.init_db import init_db
from pytest import fixture
from tests.app_routes import AppRoutes
from tests.test_config import TEST_DATA
from tests.utils.recipe_data import build_recipe_store, get_raw_no_image, get_raw_recipe
SQLITE_FILE = SQLITE_DIR.joinpath("test.db")
SQLITE_FILE.unlink(missing_ok=True)
TOKEN_URL = "/api/auth/token"
TestSessionLocal = sql_global_init(SQLITE_FILE, check_thread=False)
@ -37,16 +38,36 @@ def api_client():
SQLITE_FILE.unlink()
@fixture(scope="session")
def api_routes():
return AppRoutes()
@fixture(scope="session")
def test_image():
return TEST_DATA.joinpath("test_image.jpg")
@fixture(scope="session")
def token(api_client: requests):
def token(api_client: requests, api_routes: AppRoutes):
form_data = {"username": "changeme@email.com", "password": DEFAULT_PASSWORD}
response = api_client.post(TOKEN_URL, form_data)
response = api_client.post(api_routes.auth_token, form_data)
token = json.loads(response.text).get("access_token")
return {"Authorization": f"Bearer {token}"}
@fixture(scope="session")
def raw_recipe():
return get_raw_recipe()
@fixture(scope="session")
def raw_recipe_no_image():
return get_raw_no_image()
@fixture(scope="session")
def recipe_store():
return build_recipe_store()

View file

@ -0,0 +1,43 @@
import json
import pytest
from fastapi.testclient import TestClient
from tests.app_routes import AppRoutes
@pytest.fixture()
def page_data():
return {"name": "My New Page", "position": 0, "categories": []}
def test_create_page(api_client: TestClient, api_routes: AppRoutes, token, page_data):
response = api_client.post(api_routes.site_settings_custom_pages, json=page_data, headers=token)
assert response.status_code == 200
def test_read_page(api_client: TestClient, api_routes: AppRoutes, page_data):
response = api_client.get(api_routes.site_settings_custom_pages_id(1))
page_data["id"] = 1
page_data["slug"] = "my-new-page"
assert json.loads(response.text) == page_data
def test_update_page(api_client: TestClient, api_routes: AppRoutes, page_data, token):
page_data["id"] = 1
page_data["name"] = "My New Name"
response = api_client.put(api_routes.site_settings_custom_pages_id(1), json=page_data, headers=token)
assert response.status_code == 200
def test_delete_page(api_client: TestClient, api_routes: AppRoutes, token):
response = api_client.delete(api_routes.site_settings_custom_pages_id(1), headers=token)
assert response.status_code == 200
response = api_client.get(api_routes.site_settings_custom_pages_id(1))
assert json.loads(response.text) is None

View file

@ -0,0 +1,22 @@
from fastapi.testclient import TestClient
from tests.app_routes import AppRoutes
def test_create_group(api_client: TestClient, api_routes: AppRoutes):
assert False is True
def test_get_self_group(api_client: TestClient, api_routes: AppRoutes):
assert False is True
def test_update_group(api_client: TestClient, api_routes: AppRoutes):
assert False is True
def test_block_delete(api_client: TestClient, api_routes: AppRoutes):
assert False is True
def test_delete_group(api_client: TestClient, api_routes: AppRoutes):
assert False is True

View file

@ -0,0 +1,27 @@
import json
import pytest
from fastapi.testclient import TestClient
from tests.app_routes import AppRoutes
@pytest.fixture
def backup_data():
return {
"name": "dev_sample_data_2021-Feb-13.zip",
"force": False,
"recipes": True,
"settings": False, # ! Broken
"themes": True,
"groups": True,
"users": True,
}
def test_import(api_client: TestClient, api_routes: AppRoutes, backup_data, token):
import_route = api_routes.backups_file_name_import("dev_sample_data_2021-Feb-13.zip")
response = api_client.post(import_route, json=backup_data, headers=token)
assert response.status_code == 200
for _, value in json.loads(response.content).items():
for v in value:
assert v["status"] is True

View file

@ -1,8 +1,9 @@
import json
import pytest
from tests.test_routes.utils.routes_data import recipe_test_data
from tests.utils.routes import MEALPLAN_ALL, MEALPLAN_CREATE, MEALPLAN_PREFIX, RECIPES_CREATE_URL, RECIPES_PREFIX
from fastapi.testclient import TestClient
from tests.app_routes import AppRoutes
from tests.utils.recipe_data import RecipeTestData
def get_meal_plan_template(first=None, second=None):
@ -24,36 +25,36 @@ def get_meal_plan_template(first=None, second=None):
@pytest.fixture(scope="session")
def slug_1(api_client, token):
def slug_1(api_client: TestClient, api_routes: AppRoutes, token, recipe_store: list[RecipeTestData]):
# Slug 1
slug_1 = api_client.post(RECIPES_CREATE_URL, json={"url": recipe_test_data[0].url}, headers=token)
slug_1 = api_client.post(api_routes.recipes_create_url, json={"url": recipe_store[0].url}, headers=token)
slug_1 = json.loads(slug_1.content)
yield slug_1
api_client.delete(RECIPES_PREFIX + "/" + slug_1)
api_client.delete(api_routes.recipes_recipe_slug(slug_1))
@pytest.fixture(scope="session")
def slug_2(api_client, token):
def slug_2(api_client: TestClient, api_routes: AppRoutes, token, recipe_store: list[RecipeTestData]):
# Slug 2
slug_2 = api_client.post(RECIPES_CREATE_URL, json={"url": recipe_test_data[1].url}, headers=token)
slug_2 = api_client.post(api_routes.recipes_create_url, json={"url": recipe_store[1].url}, headers=token)
slug_2 = json.loads(slug_2.content)
yield slug_2
api_client.delete(RECIPES_PREFIX + "/" + slug_2)
api_client.delete(api_routes.recipes_recipe_slug(slug_2))
def test_create_mealplan(api_client, slug_1, slug_2, token):
def test_create_mealplan(api_client: TestClient, api_routes: AppRoutes, slug_1, slug_2, token):
meal_plan = get_meal_plan_template(slug_1, slug_2)
response = api_client.post(MEALPLAN_CREATE, json=meal_plan, headers=token)
response = api_client.post(api_routes.meal_plans_create, json=meal_plan, headers=token)
assert response.status_code == 200
def test_read_mealplan(api_client, slug_1, slug_2, token):
response = api_client.get(MEALPLAN_ALL, headers=token)
def test_read_mealplan(api_client: TestClient, api_routes: AppRoutes, slug_1, slug_2, token):
response = api_client.get(api_routes.meal_plans_all, headers=token)
assert response.status_code == 200
@ -66,23 +67,23 @@ def test_read_mealplan(api_client, slug_1, slug_2, token):
assert meals[1]["slug"] == meal_plan["meals"][1]["slug"]
def test_update_mealplan(api_client, slug_1, slug_2, token):
def test_update_mealplan(api_client: TestClient, api_routes: AppRoutes, slug_1, slug_2, token):
response = api_client.get(MEALPLAN_ALL, headers=token)
response = api_client.get(api_routes.meal_plans_all, headers=token)
existing_mealplan = json.loads(response.text)
existing_mealplan = existing_mealplan[0]
## Swap
# Swap
plan_uid = existing_mealplan.get("uid")
existing_mealplan["meals"][0]["slug"] = slug_2
existing_mealplan["meals"][1]["slug"] = slug_1
response = api_client.put(f"{MEALPLAN_PREFIX}/{plan_uid}", json=existing_mealplan, headers=token)
response = api_client.put(api_routes.meal_plans_plan_id(plan_uid), json=existing_mealplan, headers=token)
assert response.status_code == 200
response = api_client.get(MEALPLAN_ALL, headers=token)
response = api_client.get(api_routes.meal_plans_all, headers=token)
existing_mealplan = json.loads(response.text)
existing_mealplan = existing_mealplan[0]
@ -90,14 +91,14 @@ def test_update_mealplan(api_client, slug_1, slug_2, token):
assert existing_mealplan["meals"][1]["slug"] == slug_1
def test_delete_mealplan(api_client, token):
response = api_client.get(MEALPLAN_ALL, headers=token)
def test_delete_mealplan(api_client: TestClient, api_routes: AppRoutes, token):
response = api_client.get(api_routes.meal_plans_all, headers=token)
assert response.status_code == 200
existing_mealplan = json.loads(response.text)
existing_mealplan = existing_mealplan[0]
plan_uid = existing_mealplan.get("uid")
response = api_client.delete(f"{MEALPLAN_PREFIX}/{plan_uid}", headers=token)
response = api_client.delete(api_routes.meal_plans_plan_id(plan_uid), headers=token)
assert response.status_code == 200

View file

@ -0,0 +1,109 @@
import json
import shutil
from pathlib import Path
import pytest
from fastapi.testclient import TestClient
from mealie.core.config import MIGRATION_DIR
from tests.app_routes import AppRoutes
from tests.test_config import TEST_CHOWDOWN_DIR, TEST_NEXTCLOUD_DIR
# Chowdown
@pytest.fixture(scope="session")
def chowdown_zip():
zip = TEST_CHOWDOWN_DIR.joinpath("test_chowdown-gh-pages.zip")
zip_copy = TEST_CHOWDOWN_DIR.joinpath("chowdown-gh-pages.zip")
shutil.copy(zip, zip_copy)
yield zip_copy
zip_copy.unlink()
def test_upload_chowdown_zip(api_client: TestClient, api_routes: AppRoutes, chowdown_zip: Path, token):
upload_url = api_routes.migrations_source_upload("chowdown")
response = api_client.post(upload_url, files={"archive": chowdown_zip.open("rb")}, headers=token)
assert response.status_code == 200
assert MIGRATION_DIR.joinpath("chowdown", chowdown_zip.name).is_file()
def test_import_chowdown_directory(api_client: TestClient, api_routes: AppRoutes, chowdown_zip: Path, token):
delete_url = api_routes.recipes_recipe_slug("roasted-okra")
api_client.delete(delete_url, headers=token) # TODO: Manage Test Data better
selection = chowdown_zip.name
import_url = api_routes.migrations_source_file_name_import("chowdown", selection)
response = api_client.post(import_url, headers=token)
assert response.status_code == 200
report = json.loads(response.content)
assert report["failed"] == []
expected_slug = "roasted-okra"
recipe_url = api_routes.recipes_recipe_slug(expected_slug)
response = api_client.get(recipe_url)
assert response.status_code == 200
def test_delete_chowdown_migration_data(api_client: TestClient, api_routes: AppRoutes, chowdown_zip: Path, token):
selection = chowdown_zip.name
delete_url = api_routes.migrations_source_file_name_delete("chowdown", selection)
response = api_client.delete(delete_url, headers=token)
assert response.status_code == 200
assert not MIGRATION_DIR.joinpath(chowdown_zip.name).is_file()
# Nextcloud
@pytest.fixture(scope="session")
def nextcloud_zip():
zip = TEST_NEXTCLOUD_DIR.joinpath("nextcloud.zip")
zip_copy = TEST_NEXTCLOUD_DIR.joinpath("new_nextcloud.zip")
shutil.copy(zip, zip_copy)
yield zip_copy
zip_copy.unlink()
def test_upload_nextcloud_zip(api_client: TestClient, api_routes: AppRoutes, nextcloud_zip, token):
upload_url = api_routes.migrations_source_upload("nextcloud")
response = api_client.post(upload_url, files={"archive": nextcloud_zip.open("rb")}, headers=token)
assert response.status_code == 200
assert MIGRATION_DIR.joinpath("nextcloud", nextcloud_zip.name).is_file()
def test_import_nextcloud_directory(api_client: TestClient, api_routes: AppRoutes, nextcloud_zip, token):
selection = nextcloud_zip.name
import_url = api_routes.migrations_source_file_name_import("nextcloud", selection)
response = api_client.post(import_url, headers=token)
assert response.status_code == 200
report = json.loads(response.content)
assert report["failed"] == []
expected_slug = "air-fryer-shrimp"
recipe_url = api_routes.recipes_recipe_slug(expected_slug)
response = api_client.get(recipe_url)
assert response.status_code == 200
def test_delete__nextcloud_migration_data(api_client: TestClient, api_routes: AppRoutes, nextcloud_zip: Path, token):
selection = nextcloud_zip.name
delete_url = api_routes.migrations_source_file_name_delete("nextcloud", selection)
response = api_client.delete(delete_url, headers=token)
assert response.status_code == 200
assert not MIGRATION_DIR.joinpath(nextcloud_zip.name).is_file()

View file

@ -0,0 +1,95 @@
import json
import pytest
from fastapi.testclient import TestClient
from slugify import slugify
from tests.app_routes import AppRoutes
from tests.utils.recipe_data import RecipeTestData, build_recipe_store
recipe_test_data = build_recipe_store()
@pytest.mark.parametrize("recipe_data", recipe_test_data)
def test_create_by_url(api_client: TestClient, api_routes: AppRoutes, recipe_data: RecipeTestData, token):
api_client.delete(api_routes.recipes_recipe_slug(recipe_data.expected_slug), headers=token)
response = api_client.post(api_routes.recipes_create_url, json={"url": recipe_data.url}, headers=token)
assert response.status_code == 201
assert json.loads(response.text) == recipe_data.expected_slug
def test_create_by_json(api_client: TestClient, api_routes: AppRoutes, token, raw_recipe):
recipe_url = api_routes.recipes_recipe_slug("banana-bread")
api_client.delete(recipe_url, headers=token)
response = api_client.post(api_routes.recipes_create, json=raw_recipe, headers=token)
assert response.status_code == 201
assert json.loads(response.text) == "banana-bread"
def test_create_no_image(api_client: TestClient, api_routes: AppRoutes, token, raw_recipe_no_image):
response = api_client.post(api_routes.recipes_create, json=raw_recipe_no_image, headers=token)
assert response.status_code == 201
assert json.loads(response.text) == "banana-bread-no-image"
def test_read_all_post(api_client: TestClient, api_routes: AppRoutes):
response = api_client.post(api_routes.recipes, json={"properties": ["slug", "description", "rating"]})
assert response.status_code == 200
@pytest.mark.parametrize("recipe_data", recipe_test_data)
def test_read_update(api_client: TestClient, api_routes: AppRoutes, recipe_data, token):
recipe_url = api_routes.recipes_recipe_slug(recipe_data.expected_slug)
response = api_client.get(recipe_url, headers=token)
assert response.status_code == 200
recipe = json.loads(response.content)
test_notes = [
{"title": "My Test Title1", "text": "My Test Text1"},
{"title": "My Test Title2", "text": "My Test Text2"},
]
recipe["notes"] = test_notes
test_categories = ["one", "two", "three"]
recipe["recipeCategory"] = test_categories
response = api_client.put(recipe_url, json=recipe, headers=token)
assert response.status_code == 200
assert json.loads(response.text) == recipe_data.expected_slug
response = api_client.get(recipe_url)
recipe = json.loads(response.content)
assert recipe["notes"] == test_notes
assert recipe["recipeCategory"].sort() == test_categories.sort()
@pytest.mark.parametrize("recipe_data", recipe_test_data)
def test_rename(api_client: TestClient, api_routes: AppRoutes, recipe_data, token):
recipe_url = api_routes.recipes_recipe_slug(recipe_data.expected_slug)
response = api_client.get(recipe_url, headers=token)
assert response.status_code == 200
recipe = json.loads(response.text)
new_name = recipe.get("name") + "-rename"
new_slug = slugify(new_name)
recipe["name"] = new_name
response = api_client.put(recipe_url, json=recipe, headers=token)
assert response.status_code == 200
assert json.loads(response.text) == new_slug
recipe_data.expected_slug = new_slug
@pytest.mark.parametrize("recipe_data", recipe_test_data)
def test_delete(api_client: TestClient, api_routes: AppRoutes, recipe_data, token):
recipe_url = api_routes.recipes_recipe_slug(recipe_data.expected_slug)
response = api_client.delete(recipe_url, headers=token)
assert response.status_code == 200

View file

@ -1,9 +1,10 @@
import json
import pytest
from fastapi.testclient import TestClient
from tests.app_routes import AppRoutes
from mealie.schema.settings import SiteSettings
from mealie.schema.theme import SiteTheme
from tests.utils.routes import SETTINGS_PREFIX, SETTINGS_UPDATE, THEMES_CREATE, THEMES_PREFIX
@pytest.fixture(scope="function")
@ -32,57 +33,57 @@ def new_theme():
}
def test_default_settings(api_client, default_settings):
response = api_client.get(SETTINGS_PREFIX)
def test_default_settings(api_client: TestClient, api_routes: AppRoutes, default_settings):
response = api_client.get(api_routes.site_settings)
assert response.status_code == 200
assert json.loads(response.content) == default_settings
def test_update_settings(api_client, default_settings, token):
def test_update_settings(api_client: TestClient, api_routes: AppRoutes, default_settings, token):
default_settings["language"] = "fr"
default_settings["showRecent"] = False
response = api_client.put(SETTINGS_UPDATE, json=default_settings, headers=token)
response = api_client.put(api_routes.site_settings, json=default_settings, headers=token)
assert response.status_code == 200
response = api_client.get(SETTINGS_PREFIX)
response = api_client.get(api_routes.site_settings)
assert json.loads(response.content) == default_settings
def test_default_theme(api_client, default_theme):
response = api_client.get(f"{THEMES_PREFIX}/default")
def test_default_theme(api_client: TestClient, api_routes: AppRoutes, default_theme):
response = api_client.get(api_routes.themes_theme_name("default"))
assert response.status_code == 200
assert json.loads(response.content) == default_theme
def test_create_theme(api_client, new_theme, token):
def test_create_theme(api_client: TestClient, api_routes: AppRoutes, new_theme, token):
response = api_client.post(THEMES_CREATE, json=new_theme, headers=token)
response = api_client.post(api_routes.themes_create, json=new_theme, headers=token)
assert response.status_code == 200
response = api_client.get(f"{THEMES_PREFIX}/{new_theme.get('name')}", headers=token)
response = api_client.get(api_routes.themes_theme_name(new_theme.get("name")), headers=token)
assert response.status_code == 200
assert json.loads(response.content) == new_theme
def test_read_all_themes(api_client, default_theme, new_theme):
response = api_client.get(THEMES_PREFIX)
def test_read_all_themes(api_client: TestClient, api_routes: AppRoutes, default_theme, new_theme):
response = api_client.get(api_routes.themes)
assert response.status_code == 200
assert json.loads(response.content) == [default_theme, new_theme]
def test_read_theme(api_client, default_theme, new_theme):
def test_read_theme(api_client: TestClient, api_routes: AppRoutes, default_theme, new_theme):
for theme in [default_theme, new_theme]:
response = api_client.get(f"{THEMES_PREFIX}/{theme.get('name')}")
response = api_client.get(api_routes.themes_theme_name(theme.get("name")))
assert response.status_code == 200
assert json.loads(response.content) == theme
def test_delete_theme(api_client, default_theme, new_theme, token):
def test_delete_theme(api_client: TestClient, api_routes: AppRoutes, default_theme, new_theme, token):
for theme in [default_theme, new_theme]:
response = api_client.delete(f"{THEMES_PREFIX}/{theme.get('name')}", headers=token)
response = api_client.delete(api_routes.themes_theme_name(theme.get("name")), headers=token)
assert response.status_code == 200

View file

@ -0,0 +1,57 @@
import json
import pytest
from fastapi.testclient import TestClient
from mealie.schema.sign_up import SignUpToken
from tests.app_routes import AppRoutes
@pytest.fixture()
def active_link(api_client: TestClient, api_routes: AppRoutes, token):
data = {"name": "Fixture Token", "admin": True}
response = api_client.post(api_routes.users_sign_ups, json=data, headers=token)
return SignUpToken(**json.loads(response.text))
@pytest.fixture()
def sign_up_user():
return {
"fullName": "Test User",
"email": "test_user@email.com",
"admin": True,
"group": "string",
"password": "MySecretPassword",
}
def test_create_sign_up_link(api_client: TestClient, api_routes: AppRoutes, token):
data = {"name": "Test Token", "admin": False}
response = api_client.post(api_routes.users_sign_ups, json=data, headers=token)
assert response.status_code == 200
def test_new_user_signup(api_client: TestClient, api_routes: AppRoutes, active_link: SignUpToken, sign_up_user):
# Creation
response = api_client.post(api_routes.users_sign_ups_token(active_link.token), json=sign_up_user)
assert response.status_code == 200
# Login
form_data = {"username": "test_user@email.com", "password": "MySecretPassword"}
response = api_client.post(api_routes.auth_token, form_data)
assert response.status_code == 200
def test_delete_sign_up_link(
api_client: TestClient, api_routes: AppRoutes, token, active_link: SignUpToken, sign_up_user
):
response = api_client.delete(api_routes.users_sign_ups_token(active_link.token), headers=token)
assert response.status_code == 200
# Validate Token is Gone
response = api_client.get(api_routes.users_sign_ups, headers=token)
assert sign_up_user not in json.loads(response.content)

View file

@ -0,0 +1,86 @@
import json
from fastapi.testclient import TestClient
from mealie.schema.user import UserOut
from pytest import fixture
from tests.app_routes import AppRoutes
@fixture(scope="session")
def default_user():
return UserOut(id=1, fullName="Change Me", email="changeme@email.com", group="Home", admin=True)
@fixture(scope="session")
def new_user():
return UserOut(id=3, fullName="My New User", email="newuser@email.com", group="Home", admin=False)
def test_superuser_login(api_client: TestClient, api_routes: AppRoutes, token):
form_data = {"username": "changeme@email.com", "password": "MyPassword"}
response = api_client.post(api_routes.auth_token, form_data)
assert response.status_code == 200
new_token = json.loads(response.text).get("access_token")
response = api_client.get(api_routes.users_self, headers=token)
assert response.status_code == 200
return {"Authorization": f"Bearer {new_token}"}
def test_init_superuser(api_client: TestClient, api_routes: AppRoutes, token, default_user: UserOut):
response = api_client.get(api_routes.users_id(1), headers=token)
assert response.status_code == 200
assert json.loads(response.text) == default_user.dict(by_alias=True)
def test_create_user(api_client: TestClient, api_routes: AppRoutes, token, new_user):
create_data = {
"fullName": "My New User",
"email": "newuser@email.com",
"password": "MyStrongPassword",
"group": "Home",
"admin": False,
}
response = api_client.post(api_routes.users, json=create_data, headers=token)
assert response.status_code == 201
assert json.loads(response.text) == new_user.dict(by_alias=True)
assert True
def test_get_all_users(api_client: TestClient, api_routes: AppRoutes, token, new_user, default_user):
response = api_client.get(api_routes.users, headers=token)
assert response.status_code == 200
all_users = json.loads(response.text)
assert default_user.dict(by_alias=True) in all_users
assert new_user.dict(by_alias=True) in all_users
def test_update_user(api_client: TestClient, api_routes: AppRoutes, token):
update_data = {"id": 1, "fullName": "Updated Name", "email": "changeme@email.com", "group": "Home", "admin": True}
response = api_client.put(api_routes.users_id(1), headers=token, json=update_data)
assert response.status_code == 200
assert json.loads(response.text).get("access_token")
def test_reset_user_password(api_client: TestClient, api_routes: AppRoutes, token):
response = api_client.put(api_routes.users_id_reset_password(3), headers=token)
assert response.status_code == 200
form_data = {"username": "newuser@email.com", "password": "MyPassword"}
response = api_client.post(api_routes.auth_token, form_data)
assert response.status_code == 200
def test_delete_user(api_client: TestClient, api_routes: AppRoutes, token):
response = api_client.delete(api_routes.users_id(2), headers=token)
assert response.status_code == 200

View file

@ -1,25 +0,0 @@
import json
import pytest
@pytest.fixture
def backup_data():
return {
"name": "dev_sample_data_2021-Feb-13.zip",
"force": False,
"recipes": True,
"settings": False, #! Broken
"themes": True,
"groups": True,
"users": True,
}
def test_import(api_client, backup_data, token):
response = api_client.post("/api/backups/dev_sample_data_2021-Feb-13.zip/import", json=backup_data, headers=token)
assert response.status_code == 200
for key, value in json.loads(response.content).items():
for v in value:
assert v["status"] == True

View file

@ -1,101 +0,0 @@
import json
import shutil
import pytest
from mealie.core.config import MIGRATION_DIR
from tests.test_config import TEST_CHOWDOWN_DIR, TEST_NEXTCLOUD_DIR
from tests.utils.routes import MIGRATIONS_PREFIX, RECIPES_PREFIX
### Chowdown
@pytest.fixture(scope="session")
def chowdown_zip():
zip = TEST_CHOWDOWN_DIR.joinpath("test_chowdown-gh-pages.zip")
zip_copy = TEST_CHOWDOWN_DIR.joinpath("chowdown-gh-pages.zip")
shutil.copy(zip, zip_copy)
yield zip_copy
zip_copy.unlink()
def test_upload_chowdown_zip(api_client, chowdown_zip, token):
response = api_client.post(
f"{MIGRATIONS_PREFIX}/chowdown/upload", files={"archive": chowdown_zip.open("rb")}, headers=token
)
assert response.status_code == 200
assert MIGRATION_DIR.joinpath("chowdown", chowdown_zip.name).is_file()
def test_import_chowdown_directory(api_client, chowdown_zip, token):
api_client.delete(f"{RECIPES_PREFIX}/roasted-okra", headers=token) # TODO: Manage Test Data better
selection = chowdown_zip.name
response = api_client.post(f"{MIGRATIONS_PREFIX}/chowdown/{selection}/import", headers=token)
assert response.status_code == 200
report = json.loads(response.content)
assert report["failed"] == []
expected_slug = "roasted-okra"
response = api_client.get(f"{RECIPES_PREFIX}/{expected_slug}")
assert response.status_code == 200
def test_delete_chowdown_migration_data(api_client, chowdown_zip, token):
selection = chowdown_zip.name
response = api_client.delete(f"{MIGRATIONS_PREFIX}/chowdown/{selection}/delete", headers=token)
assert response.status_code == 200
assert not MIGRATION_DIR.joinpath(chowdown_zip.name).is_file()
### Nextcloud
@pytest.fixture(scope="session")
def nextcloud_zip():
zip = TEST_NEXTCLOUD_DIR.joinpath("nextcloud.zip")
zip_copy = TEST_NEXTCLOUD_DIR.joinpath("new_nextcloud.zip")
shutil.copy(zip, zip_copy)
yield zip_copy
zip_copy.unlink()
def test_upload_nextcloud_zip(api_client, nextcloud_zip, token):
response = api_client.post(
f"{MIGRATIONS_PREFIX}/nextcloud/upload", files={"archive": nextcloud_zip.open("rb")}, headers=token
)
assert response.status_code == 200
assert MIGRATION_DIR.joinpath("nextcloud", nextcloud_zip.name).is_file()
def test_import_nextcloud_directory(api_client, nextcloud_zip, token):
selection = nextcloud_zip.name
response = api_client.post(f"{MIGRATIONS_PREFIX}/nextcloud/{selection}/import", headers=token)
assert response.status_code == 200
report = json.loads(response.content)
assert report["failed"] == []
expected_slug = "air-fryer-shrimp"
response = api_client.get(f"{RECIPES_PREFIX}/{expected_slug}")
assert response.status_code == 200
def test_delete__nextcloud_migration_data(api_client, nextcloud_zip, token):
selection = nextcloud_zip.name
response = api_client.delete(f"{MIGRATIONS_PREFIX}/nextcloud/{selection}/delete", headers=token)
assert response.status_code == 200
assert not MIGRATION_DIR.joinpath(nextcloud_zip.name).is_file()

View file

@ -1,99 +0,0 @@
import json
import pytest
from slugify import slugify
from tests.test_routes.utils.routes_data import RecipeTestData, raw_recipe, raw_recipe_no_image, recipe_test_data
from tests.utils.routes import RECIPES_ALL, RECIPES_CREATE, RECIPES_CREATE_URL, RECIPES_PREFIX
@pytest.mark.parametrize("recipe_data", recipe_test_data)
def test_create_by_url(api_client, recipe_data: RecipeTestData, token):
api_client.delete(RECIPES_PREFIX + "/" + recipe_data.expected_slug, headers=token)
response = api_client.post(RECIPES_CREATE_URL, json={"url": recipe_data.url}, headers=token)
assert response.status_code == 201
assert json.loads(response.text) == recipe_data.expected_slug
def test_create_by_json(api_client, token):
api_client.delete(f"{RECIPES_PREFIX}/banana-bread", headers=token)
response = api_client.post(RECIPES_CREATE, json=raw_recipe, headers=token)
assert response.status_code == 201
assert json.loads(response.text) == "banana-bread"
def test_create_no_image(api_client, token):
response = api_client.post(RECIPES_CREATE, json=raw_recipe_no_image, headers=token)
assert response.status_code == 201
assert json.loads(response.text) == "banana-bread-no-image"
# def test_upload_image(api_client, test_image):
# data = {"image": test_image.open("rb").read(), "extension": "jpg"}
# response = api_client.post(
# "{RECIPES_PREFIX}banana-bread-no-image/update/image/", files=data
# )
# assert response.status_code == 200
# response = api_client.get("{RECIPES_PREFIX}banana-bread-no-image/update/image/")
def test_read_all_post(api_client):
response = api_client.post(RECIPES_ALL, json={"properties": ["slug", "description", "rating"]})
assert response.status_code == 200
@pytest.mark.parametrize("recipe_data", recipe_test_data)
def test_read_update(api_client, recipe_data, token):
response = api_client.get(f"{RECIPES_PREFIX}/{recipe_data.expected_slug}", headers=token)
assert response.status_code == 200
recipe = json.loads(response.content)
test_notes = [
{"title": "My Test Title1", "text": "My Test Text1"},
{"title": "My Test Title2", "text": "My Test Text2"},
]
recipe["notes"] = test_notes
test_categories = ["one", "two", "three"]
recipe["recipeCategory"] = test_categories
response = api_client.put(f"{RECIPES_PREFIX}/{recipe_data.expected_slug}", json=recipe, headers=token)
assert response.status_code == 200
assert json.loads(response.text) == recipe_data.expected_slug
response = api_client.get(f"{RECIPES_PREFIX}/{recipe_data.expected_slug}")
recipe = json.loads(response.content)
assert recipe["notes"] == test_notes
assert recipe["recipeCategory"].sort() == test_categories.sort()
@pytest.mark.parametrize("recipe_data", recipe_test_data)
def test_rename(api_client, recipe_data, token):
response = api_client.get(f"{RECIPES_PREFIX}/{recipe_data.expected_slug}", headers=token)
assert response.status_code == 200
recipe = json.loads(response.text)
new_name = recipe.get("name") + "-rename"
new_slug = slugify(new_name)
recipe["name"] = new_name
response = api_client.put(f"{RECIPES_PREFIX}/{recipe_data.expected_slug}", json=recipe, headers=token)
assert response.status_code == 200
assert json.loads(response.text) == new_slug
recipe_data.expected_slug = new_slug
@pytest.mark.parametrize("recipe_data", recipe_test_data)
def test_delete(api_client, recipe_data, token):
response = api_client.delete(f"{RECIPES_PREFIX}/{recipe_data.expected_slug}", headers=token)
assert response.status_code == 200

View file

@ -1,3 +0,0 @@

View file

@ -1,75 +0,0 @@
import json
import requests
from pytest import fixture
BASE = "/api/users"
TOKEN_URL = "/api/auth/token"
@fixture(scope="session")
def default_user():
return {"id": 1, "fullName": "Change Me", "email": "changeme@email.com", "group": "Home", "admin": True}
@fixture(scope="session")
def new_user():
return {"id": 2, "fullName": "My New User", "email": "newuser@email.com", "group": "Home", "admin": False}
def test_superuser_login(api_client: requests, token):
form_data = {"username": "changeme@email.com", "password": "MyPassword"}
response = api_client.post(TOKEN_URL, form_data)
assert response.status_code == 200
new_token = json.loads(response.text).get("access_token")
response = api_client.get("/api/users/self", headers=token)
assert response.status_code == 200
return {"Authorization": f"Bearer {new_token}"}
def test_init_superuser(api_client: requests, token, default_user):
response = api_client.get(f"{BASE}/1", headers=token)
assert response.status_code == 200
assert json.loads(response.text) == default_user
def test_create_user(api_client: requests, token, new_user):
create_data = {
"fullName": "My New User",
"email": "newuser@email.com",
"password": "MyStrongPassword",
"group": "Home",
"admin": False,
}
response = api_client.post(f"{BASE}", json=create_data, headers=token)
assert response.status_code == 201
assert json.loads(response.text) == new_user
assert True
def test_get_all_users(api_client: requests, token, new_user, default_user):
response = api_client.get(f"{BASE}", headers=token)
assert response.status_code == 200
assert json.loads(response.text) == [default_user, new_user]
def test_update_user(api_client: requests, token):
update_data = {"id": 1, "fullName": "Updated Name", "email": "changeme@email.com", "group": "Home", "admin": True}
response = api_client.put(f"{BASE}/1", headers=token, json=update_data)
assert response.status_code == 200
assert json.loads(response.text).get("access_token")
def test_delete_user(api_client: requests, token):
response = api_client.delete(f"{BASE}/2", headers=token)
assert response.status_code == 200

View file

@ -1,111 +0,0 @@
class RecipeTestData:
def __init__(self, url, expected_slug) -> None:
self.url: str = url
self.expected_slug: str = expected_slug
recipe_test_data = [
RecipeTestData(
url="https://www.bonappetit.com/recipe/spinach-thepla-and-vaghareli-dahi",
expected_slug="thepla-recipe-with-vaghareli-dahi",
),
RecipeTestData(
url="https://www.bonappetit.com/recipe/classic-coleslaw",
expected_slug="traditional-coleslaw-recipe",
),
]
raw_recipe = {
"name": "Banana Bread",
"description": "From Angie's mom",
"image": "banana-bread.jpg",
"recipeYield": "",
"recipeIngredient": [
"4 bananas",
"1/2 cup butter",
"1/2 cup sugar",
"2 eggs",
"2 cups flour",
"1/2 tsp baking soda",
"1 tsp baking powder",
"pinch salt",
"1/4 cup nuts (we like pecans)",
],
"recipeInstructions": [
{
"@type": "Beat the eggs, then cream with the butter and sugar",
"text": "Beat the eggs, then cream with the butter and sugar",
},
{
"@type": "Mix in bananas, then flour, baking soda/powder, salt, and nuts",
"text": "Mix in bananas, then flour, baking soda/powder, salt, and nuts",
},
{
"@type": "Add to greased and floured pan",
"text": "Add to greased and floured pan",
},
{
"@type": "Bake until brown/cracked, toothpick comes out clean",
"text": "Bake until brown/cracked, toothpick comes out clean",
},
],
"totalTime": "None",
"prepTime": None,
"performTime": None,
"slug": "",
"categories": [],
"tags": ["breakfast", " baking"],
"dateAdded": "2021-01-12",
"notes": [],
"rating": 0,
"orgURL": None,
"extras": {},
}
raw_recipe_no_image = {
"name": "Banana Bread No Image",
"description": "From Angie's mom",
"image": "",
"recipeYield": "",
"recipeIngredient": [
"4 bananas",
"1/2 cup butter",
"1/2 cup sugar",
"2 eggs",
"2 cups flour",
"1/2 tsp baking soda",
"1 tsp baking powder",
"pinch salt",
"1/4 cup nuts (we like pecans)",
],
"recipeInstructions": [
{
"@type": "Beat the eggs, then cream with the butter and sugar",
"text": "Beat the eggs, then cream with the butter and sugar",
},
{
"@type": "Mix in bananas, then flour, baking soda/powder, salt, and nuts",
"text": "Mix in bananas, then flour, baking soda/powder, salt, and nuts",
},
{
"@type": "Add to greased and floured pan",
"text": "Add to greased and floured pan",
},
{
"@type": "Bake until brown/cracked, toothpick comes out clean",
"text": "Bake until brown/cracked, toothpick comes out clean",
},
],
"totalTime": "None",
"prepTime": None,
"performTime": None,
"slug": "",
"categories": [],
"tags": ["breakfast", " baking"],
"dateAdded": "2021-01-12",
"notes": [],
"rating": 0,
"orgURL": None,
"extras": {},
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

View file

@ -1,63 +0,0 @@
{
"@context": "http:\/\/schema.org",
"@type": "Recipe",
"name": "Air Fryer Shrimp",
"author": {
"@type": "Person",
"name": "Anna"
},
"description": "These Air Fryer Shrimp are plump, juicy and perfectly seasoned! This healthy dish is ready in just 8 minutes and requires pantry staples to make it.",
"datePublished": "2020-07-13T16:48:25+00:00",
"image": "https:\/\/www.crunchycreamysweet.com\/wp-content\/uploads\/2020\/07\/air-fryer-shrimp-A-480x270.jpg",
"recipeYield": 4,
"prepTime": "PT0H15M",
"cookTime": "PT0H8M",
"totalTime": "PT0H23M",
"recipeIngredient": [
"1 lb shrimp",
"2 teaspoons olive oil",
"\u00bd teaspoon garlic powder",
"\u00bc teaspoon paprika",
"\u00bd teaspoon Italian seasoning",
"\u00bd teaspoon salt",
"\u00bc teaspoon black pepper"
],
"recipeInstructions": [
"Cleaning the shrimp by removing shells and veins. Run under tap water, then pat dry with paper towel.",
"Mix oil with seasoning in a small bowl.",
"Brush shrimp with seasoning mixture on both sides.",
"Arrange shrimp in air fryer basket or rack, in a single layer.",
"Cook at 400 degrees F for 8 minutes (no need to turn them).",
"Serve."
],
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "5",
"ratingCount": "4"
},
"recipeCategory": "Main Course",
"recipeCuisine": [
"American"
],
"keywords": "air fryer shrimp",
"nutrition": {
"@type": "NutritionInformation",
"calories": "134 kcal",
"carbohydrateContent": "1 g",
"proteinContent": "23 g",
"fatContent": "4 g",
"saturatedFatContent": "1 g",
"cholesterolContent": "286 mg",
"sodiumContent": "1172 mg",
"fiberContent": "1 g",
"sugarContent": "1 g",
"servingSize": "1 serving"
},
"@id": "https:\/\/www.crunchycreamysweet.com\/air-fryer-shrimp\/#recipe",
"isPartOf": {
"@id": "https:\/\/www.crunchycreamysweet.com\/air-fryer-shrimp\/#article"
},
"mainEntityOfPage": "https:\/\/www.crunchycreamysweet.com\/air-fryer-shrimp\/#webpage",
"tool": [],
"url": "https:\/\/www.crunchycreamysweet.com\/air-fryer-shrimp\/"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

View file

@ -1,259 +0,0 @@
{
"@context": "http:\/\/schema.org",
"@type": "Recipe",
"mainEntityOfPage": "https:\/\/www.allrecipes.com\/recipe\/8975\/chicken-parmigiana\/",
"name": "Chicken Parmigiana",
"image": "https:\/\/imagesvc.meredithcorp.io\/v3\/mm\/image?url=https%3A%2F%2Fimages.media-allrecipes.com%2Fuserphotos%2F10037.jpg",
"datePublished": "1999-04-27T12:40:19.000Z",
"description": "This is a very nice dinner for two. Serve it with your favorite pasta and tossed greens.",
"prepTime": "PT0H30M",
"cookTime": "PT1H0M",
"totalTime": "PT1H30M",
"recipeYield": 2,
"recipeIngredient": [
"1 egg, beaten",
"2 ounces dry bread crumbs",
"2 skinless, boneless chicken breast halves",
"\u00be (16 ounce) jar spaghetti sauce",
"2 ounces shredded mozzarella cheese",
"\u00bc cup grated Parmesan cheese"
],
"recipeInstructions": [
"Preheat oven to 350 degrees F (175 degrees C). Lightly grease a medium baking sheet.\n",
"Pour egg into a small shallow bowl. Place bread crumbs in a separate shallow bowl. Dip chicken into egg, then into the bread crumbs. Place coated chicken on the prepared baking sheet and bake in the preheated oven for 40 minutes, or until no longer pink and juices run clear.\n",
"Pour 1\/2 of the spaghetti sauce into a 7x11 inch baking dish. Place chicken over sauce, and cover with remaining sauce. Sprinkle mozzarella and Parmesan cheeses on top and return to the preheated oven for 20 minutes.\n"
],
"recipeCategory": "World Cuisine Recipes",
"recipeCuisine": [],
"author": [
{
"@type": "Person",
"name": "Candy"
}
],
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": 4.580034423407917,
"ratingCount": 1743,
"itemReviewed": "Chicken Parmigiana",
"bestRating": "5",
"worstRating": "1"
},
"nutrition": {
"@type": "NutritionInformation",
"calories": "528.3 calories",
"carbohydrateContent": "44.9 g",
"cholesterolContent": "184.1 mg",
"fatContent": "18.3 g",
"fiberContent": "5.6 g",
"proteinContent": "43.5 g",
"saturatedFatContent": "7.6 g",
"servingSize": null,
"sodiumContent": "1309.5 mg",
"sugarContent": "17.2 g",
"transFatContent": null,
"unsaturatedFatContent": null
},
"review": [
{
"@type": "Review",
"datePublished": "2004-02-10T10:18:54.927Z",
"reviewBody": "This is a DELICIOUS basic recipe. I have been doing a similar one for years. I also, prefer adding a few more spices TO THE BREAD CRUMBS,like basil, oregano, garlic powder, salt, fresh cracked pepper and onion powder, and a few TBSP of the parmensan cheese;not only ON IT later. For some reason these spices (added separately) are good, but we don't like with an pre-mix of \"Italian\"spice. It seems to taste a little \"soapy\". Not sure which spice does that to it.? Some suggested to \"double dip\" in bread crumbs;if you do, you should really LIKE a heavy battering. It was too thick for our tastes(esp. since you bake in the sauce; to me,the bottom gets a little mushy, and it just adds extra fat and calories). I also use a cookie cooling \"RACK\" SET ON TOP of a baking sheet, to bake the chicken on instead of just on the cookie sheet pan. It comes out much crisper; letting air get to the BOTTOM of the chicken,also. Also,I wait to spoon the SECOND 1\/2 of the sauce UNTIL SERVING, the chicken will stay crisper,(even with the cheese on top). Obviously, we like the chicken on the crisp side (but we don't want to deep fry).\r\nFor company, put the chicken (with just the cheese baked on top) ON TOP of a small mound of spaghetti and sauce,or any pasta; It makes for a delicious looking presentation. A side salad with some sort of CREAMY dressing seems to compliment the red sauce, and completes the meal wonderfully. We get cravings for this one about 2c a month!",
"reviewRating": {
"@type": "Rating",
"worstRating": "1",
"bestRating": "5",
"ratingValue": 4
},
"author": {
"@type": "Person",
"name": "somethingdifferentagain?!",
"image": null,
"sameAs": "https:\/\/www.allrecipes.com\/cook\/342976\/"
}
},
{
"@type": "Review",
"datePublished": "2004-01-23T16:37:02.013Z",
"reviewBody": "This was an extremely easy, very tasty recipe. As many others suggested, I only put sauce on the bottom of the chicken and then spooned a little over the top when serving. I think the recipe could be improved, though, by (1) pounding the chicken to a uniform thickness and (2) by spicing up the bread crumbs. I used Italian bread crumbs but next time will sprinkle pepper on the chicken before dredging through the crumbs, and I also plan to add more Italian seasoning and maybe a little parmesan to the crumbs. Both these steps, in my opinion, would take this from a really good recipe to an excellent dish!",
"reviewRating": {
"@type": "Rating",
"worstRating": "1",
"bestRating": "5",
"ratingValue": 4
},
"author": {
"@type": "Person",
"name": "JBAGNALL",
"image": null,
"sameAs": "https:\/\/www.allrecipes.com\/cook\/642772\/"
}
},
{
"@type": "Review",
"datePublished": "2005-11-19T20:22:40.53Z",
"reviewBody": "I BRINED my chicken in 4 cups water , 1\/2 cup kosher salt (1\/4 table salt) \u00bd cup sugar for 30 minutes. No need to brine if you are using quick frozen chicken that has been enhanced. Kosher chicken is prebrined. Brining=juicy chicken. Took brined chicken, cut off thin edges, pounded out & shook chicken w\/flour (preflouring allows bread crumbs to stick) in a Ziploc-letting floured chicken sit for 5 min. I heated 6 TBS vegetable oil till it shimmered & then added 2 TBS butter to my pan, reserving half of this mixture for my second batch. Bread crumb mixture: I use \u00bd cup seasoned bread crumbs(same as 2 ounces), \u00bd cup grated parmesan( double what recipe calls for), 1tsp. Mrs. Dash Garlic and Herb, \u00bd tsp. garlic powder, \u00bd tsp, onion powder, \u00bd tsp. Italian seasoning & a pinch of pepper. Took pre-floured chicken, coated it with egg mixture, then dipped in bread crumbs & FRIED the chicken to a medium golden brown. Shook some parmesan on them right away when done frying to absorb any oil. Side-by side I plated plain spaghetti noodles & cutlets, w\/2 TBSP sauce on cutlet & desired amount of sauce on pasta, covered in cheese & baked each individual plate till cheese melted, serving them straight out of the oven. \r\nThe reviews on this were probably the best I have ever gotten, I used to work in an Italian Restaurant owned by NY Italians & have picked up some techniques. My Fettuccine Alfredo used to be my husband favorite dish, after last night he told me he has a new favorite. \r\n",
"reviewRating": {
"@type": "Rating",
"worstRating": "1",
"bestRating": "5",
"ratingValue": 5
},
"author": {
"@type": "Person",
"name": "KC MARTEL",
"image": null,
"sameAs": "https:\/\/www.allrecipes.com\/cook\/526291\/"
}
},
{
"@type": "Review",
"datePublished": "2003-10-22T15:32:26.607Z",
"reviewBody": "After several Chicken Parm recipes THIS is THE ONE:-) I've finally found one that we all love! It's simple and it's darned good:-) I will definately make this recipe again and again; thanks so much:-)",
"reviewRating": {
"@type": "Rating",
"worstRating": "1",
"bestRating": "5",
"ratingValue": 5
},
"author": {
"@type": "Person",
"name": "STARCHILD1166",
"image": null,
"sameAs": "https:\/\/www.allrecipes.com\/cook\/736533\/"
}
},
{
"@type": "Review",
"datePublished": "2003-11-14T16:55:26.39Z",
"reviewBody": "This chicken was so easy to make and turned out excellent! Used Best Marinara Sauce Yet (found here as well)instead of regular spaghetti sauce. This added even more flavor.",
"reviewRating": {
"@type": "Rating",
"worstRating": "1",
"bestRating": "5",
"ratingValue": 5
},
"author": {
"@type": "Person",
"name": "Alison",
"image": null,
"sameAs": "https:\/\/www.allrecipes.com\/cook\/516223\/"
}
},
{
"@type": "Review",
"datePublished": "2003-01-23T04:38:19.873Z",
"reviewBody": "I REALLY liked this recipe. I made my own spaghetti sauce and used parmesan reggiano. I also skipped dipping the breasts in egg as I thought it was unnecessary and it was. Cooking temp. and time are accurate. Even my fussy fiance liked this. I'll definitely make this again.",
"reviewRating": {
"@type": "Rating",
"worstRating": "1",
"bestRating": "5",
"ratingValue": 4
},
"author": {
"@type": "Person",
"name": "CSANDST1",
"image": null,
"sameAs": "https:\/\/www.allrecipes.com\/cook\/115553\/"
}
},
{
"@type": "Review",
"datePublished": "2003-08-05T20:26:00.81Z",
"reviewBody": "Wow! This was really tasty and simple. Something quick to make when you can't spend too much time figuring out what's for dinner. Also great on a toasted roll\/hero as a sandwich. I varied the recipe a little by adding some parmesan cheese (big cheese lover that I am!), garlic powder, onion powder and some salt into the bread crumbs and then mixing it up before breading the chicken with it. Also added a little salt to the beaten egg to make sure the chicken wouldn't end up bland, but that's just my preference. In response to the one reviewer who wanted thicker breading, what I did was double dip the chicken - coat first with the bread crumbs, then dip into the beaten egg and re-coat with breadcrumbs before actually baking (this would require some more breadcrumbs and probably another egg). Excellent recipe! =]",
"reviewRating": {
"@type": "Rating",
"worstRating": "1",
"bestRating": "5",
"ratingValue": 5
},
"author": {
"@type": "Person",
"name": "LIZCHAO74",
"image": null,
"sameAs": "https:\/\/www.allrecipes.com\/cook\/511187\/"
}
},
{
"@type": "Review",
"datePublished": "2003-07-23T07:53:37.18Z",
"reviewBody": "Wonderful chicken recipe! I have made this several times. One night we were craving it and I didn't have any bottled spaghetti sauce. I poured a 14 ounce can of tomato sauce in a microwave bowl added 2t Italian Seasoning and 1t of garlic powder cooked on high for 6 minutes and ended up with a rich thick sauce for the chicken.",
"reviewRating": {
"@type": "Rating",
"worstRating": "1",
"bestRating": "5",
"ratingValue": 4
},
"author": {
"@type": "Person",
"name": "MAGGIE MCGUIRE",
"image": null,
"sameAs": "https:\/\/www.allrecipes.com\/cook\/392086\/"
}
},
{
"@type": "Review",
"datePublished": "2008-06-10T21:54:38.893Z",
"reviewBody": "This is gonna be one of those it\u2019s a good recipe when you completely change it reviews. I did originally follow the recipe and the chicken tasted like it had been in breaded in cardboard. It just was not appetizing. However there is a great breaded chicken recipe on this site, garlic chicken. Made this simple and easy and oh so TASTY. I got great reviews. Here is what I did. Took \u00bc cup olive oil with 3 cloves garlic crushed and heated in microwave for 30 sec. Then coated the chicken in the oil and dipped in a mixture of \u00bd Italian seasoned bread crumbs and \u00bd parmesan cheese (double coat if u like thick breading). Cooked in oven at 325 for 20min (on a foil covered cookie sheet to make clean up easy). Set them in a casserole dish on top of about \u00bd a jar of spaghetti sauce for 3 chicken breast. Covered the breast with slices of mozzarella cheese and baked for another 20-25 minutes. Top with parmesan cheese. This turned out really really yummy and smells sooo good while it\u2019s cooking. ",
"reviewRating": {
"@type": "Rating",
"worstRating": "1",
"bestRating": "5",
"ratingValue": 4
},
"author": {
"@type": "Person",
"name": "ANGEL.9",
"image": null,
"sameAs": "https:\/\/www.allrecipes.com\/cook\/218599\/"
}
},
{
"@type": "Review",
"datePublished": "2006-02-02T19:05:24.607Z",
"reviewBody": "Check out \"Tomato Chicken Parmesan\" on this site for a truly fabulous chicken parm recipe. Every time I make that one people say its the best chicken parm they every had. No matter what kind you make though always pound your chicken breasts it will help immensely keeping the chicken tender and moist.",
"reviewRating": {
"@type": "Rating",
"worstRating": "1",
"bestRating": "5",
"ratingValue": 3
},
"author": {
"@type": "Person",
"name": "MomSavedbyGrace",
"image": null,
"sameAs": "https:\/\/www.allrecipes.com\/cook\/1366670\/"
}
}
],
"video": {
"@context": "http:\/\/schema.org",
"@type": "VideoObject",
"name": "Chicken Parmigiana",
"description": "Make this quick and easy version of chicken Parmigiana.",
"uploadDate": "2012-05-23T22:01:40.476Z",
"duration": "PT2M18.43S",
"thumbnailUrl": "https:\/\/imagesvc.meredithcorp.io\/v3\/mm\/image?url=https%3A%2F%2Fcf-images.us-east-1.prod.boltdns.net%2Fv1%2Fstatic%2F1033249144001%2F15c9e37d-979a-4c2c-a35d-fc3f436b0047%2F6b7f7749-9989-4707-971e-8578e60c0670%2F160x90%2Fmatch%2Fimage.jpg",
"publisher": {
"@type": "Organization",
"name": "Allrecipes",
"url": "https:\/\/www.allrecipes.com",
"logo": {
"@type": "ImageObject",
"url": "https:\/\/www.allrecipes.com\/img\/logo.png",
"width": 209,
"height": 60
},
"sameAs": [
"https:\/\/www.facebook.com\/allrecipes",
"https:\/\/twitter.com\/Allrecipes",
"https:\/\/www.pinterest.com\/allrecipes\/",
"https:\/\/www.instagram.com\/allrecipes\/"
]
},
"embedUrl": "https:\/\/players.brightcove.net\/1033249144001\/default_default\/index.html?videoId=1653498713001"
},
"keywords": "",
"tool": [],
"url": "https:\/\/www.allrecipes.com\/recipe\/8975\/chicken-parmigiana\/"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

View file

@ -1,89 +0,0 @@
{
"@context": "http:\/\/schema.org",
"@type": "Recipe",
"name": "Skillet Shepherd's Pie",
"author": {
"@type": "Person",
"name": "Joanna Cismaru"
},
"description": "This Skillet Shepherd's Pie recipe, also known as cottage pie, is loaded with flavorful beef and veggies, topped with fluffy and creamy mashed potatoes, then baked to perfection!",
"datePublished": "2019-03-16T20:15:47+00:00",
"image": "https:\/\/www.jocooks.com\/wp-content\/uploads\/2016\/12\/skillet-shepherds-pie-1-2-480x270.jpg",
"video": {
"name": "Skillet Shepherd's Pie",
"description": "This skillet shepherd\u2019s pie is loaded with flavorful beef and veggies then topped with fluffy and creamy mashed potatoes, then baked to perfection!",
"thumbnailUrl": "https:\/\/content.jwplatform.com\/thumbs\/HGr48vds-720.jpg",
"contentUrl": "https:\/\/content.jwplatform.com\/videos\/HGr48vds.mp4",
"uploadDate": "2018-03-08T16:13:05.000Z",
"@type": "VideoObject"
},
"recipeYield": 1,
"prepTime": "PT0H15M",
"cookTime": "PT1H10M",
"totalTime": "PT1H25M",
"recipeIngredient": [
"1 tbsp olive oil",
"1 1\/4 lb ground beef (lean)",
"1\/2 tsp salt (or to taste)",
"1\/2 tsp pepper (or to taste)",
"1 large onion (chopped)",
"1 clove garlic (minced)",
"1\/2 tsp red pepper flakes",
"2 tbsp Worcestershire sauce",
"1.9 oz onion soup mix (I used Knorr, 55g pkg)",
"1 cup beef broth (low sodium)",
"2 cups frozen veggies (I used mix of peas, carrots, green beans and corn)",
"6 large potatoes (peeled and cut into cubes)",
"4 tbsp butter (softened)",
"2\/3 cup milk",
"1\/4 cup Parmesan cheese",
"1\/2 tsp salt (or to taste)",
"1\/2 tsp white pepper (or to taste)",
"1 tbsp parsley (fresh, for garnish)"
],
"recipeInstructions": [
"Boil the potatoes: Start by first cooking the potatoes in boiling water for about 15 minutes or until fork tender. While the potatoes are cooking, you can prepare the meat mixture.",
"Prepare the meat mixture: Heat the oil in a large skillet over medium heat. Add the ground beef to the skillet, season it with the salt and pepper and cook it for abut 5 minutes or until it's no longer pink, breaking it up as you go along.",
"Add the onion and garlic and cook for 3 more minutes until the onion softens and becomes translucent. Add the pepper flakes, Worcestershire sauce, onion soup mix, beef broth and stir. Stir in the frozen veggies and cook for a couple more minutes. Set aside.",
"Preheat the oven 350 F degrees.",
"Prepare the mashed potatoes: Drain the potatoes then add them to a large bowl. Add in the butter and using a potato masher, mash until smooth. Add the milk, Parmesan cheese, salt pepper and mash a bit a more until smooth.",
"Finish assembling the shepherd's pie: Spread the potatoes over the meat and smooth with a spoon. Take a fork and rough up the top a bit and garnish with a bit of parsley.",
"Bake: Place the skillet on a baking sheet, then place it in the oven and bake for 40 minutes until golden brown on top.",
"Garnish with more parsley and pepper and serve warm."
],
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.48",
"ratingCount": "505"
},
"recipeCategory": "Main Course",
"recipeCuisine": [
"American"
],
"keywords": "cottage pie,shepherd's pie,skillet shepherd's pie",
"nutrition": {
"@type": "NutritionInformation",
"calories": "252 kcal",
"carbohydrateContent": "14 g",
"proteinContent": "19 g",
"fatContent": "12 g",
"saturatedFatContent": "6 g",
"cholesterolContent": "63 mg",
"sodiumContent": "1165 mg",
"fiberContent": "2 g",
"sugarContent": "2 g",
"servingSize": "1 serving"
},
"@id": "https:\/\/www.jocooks.com\/recipes\/skillet-shepherds-pie\/#recipe",
"isPartOf": {
"@id": "https:\/\/www.jocooks.com\/recipes\/skillet-shepherds-pie\/#article"
},
"mainEntityOfPage": "https:\/\/www.jocooks.com\/recipes\/skillet-shepherds-pie\/#webpage",
"url": "https:\/\/www.jocooks.com\/recipes\/skillet-shepherds-pie\/",
"id": "4485",
"dateCreated": "0",
"dateModified": "1607461134",
"printImage": "false",
"imageUrl": "\/nextcloud\/index.php\/apps\/cookbook\/recipes\/4485\/image?size=full",
"tool": []
}

File diff suppressed because one or more lines are too long

View file

@ -1,103 +0,0 @@
{
"@context": "http://schema.org",
"@type": "Recipe",
"image": "https://img.chefkoch-cdn.de/rezepte/2235331358009600/bilder/864648/crop-960x540/pizza-knoblauch-champignon-paprika-vegan.jpg",
"recipeCategory": "Gem\u00fcse",
"recipeIngredient": [
"300 g Weizenmehl (Type 550)",
"1 Pck. Trockenhefe",
"1 TL Salz",
"170 ml Wasser",
"6 EL \u00d6l (Knoblauch\u00f6l oder Oliven\u00f6l)",
"1 EL Tomatenmark",
"n. B. Knoblauch , gew\u00fcrfelt",
"2 Spitzpaprika oder Gem\u00fcsepaprika, rot",
"250 g Champignons",
"1 Zwiebel(n)",
" Salz und Pfeffer",
" Kr\u00e4uter , italienische, frisch oder getrocknet",
" Harissa"
],
"name": "Pizza Knoblauch Champignon Paprika - vegan",
"description": "Pizza Knoblauch Champignon Paprika - vegan - f\u00fcr Nicht-Veganer nat\u00fcrlich mit K\u00e4se zu belegen. \u00dcber 51 Bewertungen und f\u00fcr raffiniert befunden. Mit \u25ba Portionsrechner \u25ba Kochbuch \u25ba Video-Tipps!",
"recipeInstructions": "Die Zutaten f\u00fcr den Teig verkneten und ca. 40 Minuten an einem warmen Ort gehen lassen. In der Zwischenzeit eine beliebige Anzahl Knoblauchzehen fein w\u00fcrfeln (ich bedecke die Pizza nahezu fl\u00e4chendeckend), die Zwiebel ebenfalls w\u00fcrfeln, Paprika und Champignons klein schneiden. Das \u00d6l mit Tomatenmark, Salz und Pfeffer vermischen. \r\n\r\nDen fertigen Teig ausrollen und auf ein Blech legen (ich benutze eine Pflaumenkuchen-Backform). Die \u00d6lmischung mit einem Backpinsel gleichm\u00e4\u00dfig auf dem Teig verteilen, danach mit dem Knoblauch, den Champignons, der Paprika und den Zwiebeln belegen. \r\n\r\nNun die Pizza mit Salz, Pfeffer, Kr\u00e4utern und Harissa kr\u00e4ftig w\u00fcrzen und bei 250\u00b0C ca. 10 - 15 Minuten backen. Der Teig ist als Grundteig zu betrachten und l\u00e4sst sich nat\u00fcrlich mit allem M\u00f6glichen an Gem\u00fcse belegen.",
"author": {
"@type": "Person",
"name": "healing21"
},
"publisher": {
"@type": "Organization",
"name": "Chefkoch.de"
},
"datePublished": "2013-01-14",
"prepTime": "P0DT0H20M",
"cookTime": "P0DT0H15M",
"totalTime": "P0DT1H15M",
"recipeYield": "2 Portion(en)",
"aggregateRating": {
"@type": "AggregateRating",
"ratingCount": 51,
"ratingValue": 4.57,
"reviewCount": 34,
"worstRating": 0,
"bestRating": 5
},
"keywords": [
"Gem\u00fcse",
"Hauptspeise",
"Backen",
"Vegetarisch",
"einfach",
"Vegan",
"Pizza",
"Pilze"
],
"reviews": [
{
"@type": "Review",
"reviewBody": " Sehr gutes Basis Rezept!\n\nHab noch Salami, Kochschinken und K\u00e4se dazu gemacht, sonst schmeckt es ja nach nichts. \n\nErgebnis: 1. Klasse! Sehr fein! ",
"datePublished": "2020-04-21",
"author": {
"@type": "Person",
"name": "eierkopp1824"
}
},
{
"@type": "Review",
"reviewBody": "Hallo,\r\nhabe den Teig gut zwei Stunden gehen lassen und dann wie im Rezept angegeben weiter verarbeitet. Da ich noch einige Schinkenw\u00fcrfel und etwas Fetak\u00e4se im K\u00fchlschrank hatte, wurden diese ebenfalls auf dem Belag verteilt. Ich habe die Pizza auf der untersten Schiene im Backofen gebacken. Der Boden ist nach dem Backen sch\u00f6n knusprig. Es hat mir und meinem Mitesser sehr gut geschmeckt.\r\nLG von Sternek\u00f6chin2011",
"datePublished": "2020-03-10",
"author": {
"@type": "Person",
"name": "Sternek\u00f6chin2011"
}
},
{
"@type": "Review",
"reviewBody": "Echt f\u00fcr mich die leckerste Pizza auf der Welt! Auch bei meiner Familie kommt sie super an und \u00fcberlebt nicht lange. :)\nDen Belag kann man ja variieren wie man will. ",
"datePublished": "2020-02-20",
"author": {
"@type": "Person",
"name": "Leo090800"
}
},
{
"@type": "Review",
"reviewBody": "Beste Pizza, die ich je gegessen habe! Sooo lecker! Habe f\u00fcr den Teig Dinkelvollkornmehl genommen und den Belag noch mit ein paar Chiliflocken verfeinert. ",
"datePublished": "2018-04-15",
"author": {
"@type": "Person",
"name": "Sunny_Eyes"
}
},
{
"@type": "Review",
"reviewBody": "Der Teig ist super, ebenso wie die Sauce! Habe anstelle von normalem Salz Basilikumsalz in den Teig gegeben, das gibt dem ganzen einen besonderen Geschmack.Statt Paprika und Knobi habe ich K\u00e4se und Rucola hinzuef\u00fcgt, den Salat erst nach dem Backen. Die wird sicherlich nochmal gemacht! Da ich nur eine Pizza gemacht habe, habe ich den restlichen Teig eingefroren. Foto ist unterwegs!",
"datePublished": "2018-02-14",
"author": {
"@type": "Person",
"name": "Chiqryn"
}
}
],
"url": "https://www.chefkoch.de/rezepte/2235331358009600/Pizza-Knoblauch-Champignon-Paprika-vegan.html"
}

View file

@ -1,86 +0,0 @@
{
"@context": "http://schema.org/",
"@type": "Recipe",
"name": "The Best Homemade Salsa Recipe",
"author": {
"@type": "Person",
"name": "Sommer Collier"
},
"description": "How To Make Delicious Salsa: Secrets of making the Best Homemade Salsa Recipe! This restaurant style salsa recipe is loaded with flavor, has an amazing texture, and a secret ingredient.",
"datePublished": "2020-02-01T00:00:30+00:00",
"image": [
"https://www.aspicyperspective.com/wp-content/uploads/2019/02/the-best-homemade-salsa-recipe-100.jpg",
"https://www.aspicyperspective.com/wp-content/uploads/2019/02/the-best-homemade-salsa-recipe-100-500x500.jpg",
"https://www.aspicyperspective.com/wp-content/uploads/2019/02/the-best-homemade-salsa-recipe-100-500x375.jpg",
"https://www.aspicyperspective.com/wp-content/uploads/2019/02/the-best-homemade-salsa-recipe-100-480x270.jpg"
],
"video": {
"name": "The Best Homemade Salsa Recipe",
"description": "We\u2019re sharing our secrets for making The Best Homemade Salsa Recipe we\u2019ve ever tried. Healthy, fresh, and easy to adjust!",
"thumbnailUrl": "https://content.jwplatform.com/thumbs/rPi8NdK6-720.jpg",
"contentUrl": "https://content.jwplatform.com/videos/rPi8NdK6.mp4",
"uploadDate": "2017-03-22T16:24:09.000Z",
"@type": "VideoObject"
},
"recipeYield": [
"20",
"20 (5 cups)"
],
"prepTime": "PT5M",
"totalTime": "PT5M",
"recipeIngredient": [
"4 ripe tomatoes, (cored and quartered)",
"1 red onion, (peeled and quartered)",
"3 garlic cloves, (peeled)",
"3 jalapenos, (stemmed and seeded (you can\u00a0substitute 1-2 habanero or serrano peppers.))",
"1/3 cup fresh cilantro",
"3 tablespoons fresh lime juice",
"2-3 teaspoons ground cumin",
"2-3 teaspoons sugar ((optional))",
"1 1/2 teaspoons salt",
"15 ounces crushed San Marzano tomatoes ((1 can))",
"4.5 ounces diced green chiles, (mild, medium, or hot (1 can))"
],
"recipeInstructions": [
{
"@type": "HowToStep",
"text": "Place the fresh tomatoes, onion, garlic, peppers, cilantro, lime juice, 2 teaspoons cumin, 2 teaspoons sugar (if using), and salt in a food processor. Pulse until the contents are fine and well blended.",
"name": "Place the fresh tomatoes, onion, garlic, peppers, cilantro, lime juice, 2 teaspoons cumin, 2 teaspoons sugar (if using), and salt in a food processor. Pulse until the contents are fine and well blended.",
"url": "https://www.aspicyperspective.com/best-homemade-salsa-recipe/#wprm-recipe-61842-step-0-0"
},
{
"@type": "HowToStep",
"text": "Pour in the crushed tomatoes and green chiles. Puree until mostly smooth. Taste, then add more cumin and sugar if desired. Refrigerate until ready to serve.",
"name": "Pour in the crushed tomatoes and green chiles. Puree until mostly smooth. Taste, then add more cumin and sugar if desired. Refrigerate until ready to serve.",
"url": "https://www.aspicyperspective.com/best-homemade-salsa-recipe/#wprm-recipe-61842-step-0-1"
}
],
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.98",
"ratingCount": "201"
},
"recipeCategory": [
"Appetizer",
"Snack"
],
"recipeCuisine": [
"American",
"Mexican"
],
"keywords": "Homemade Salsa, Salsa, The Best Salsa Recipe",
"nutrition": {
"@type": "NutritionInformation",
"servingSize": "0.25 cup",
"calories": "19 kcal",
"carbohydrateContent": "4 g",
"sodiumContent": "230 mg",
"sugarContent": "2 g"
},
"@id": "https://www.aspicyperspective.com/best-homemade-salsa-recipe/#recipe",
"isPartOf": {
"@id": "https://www.aspicyperspective.com/best-homemade-salsa-recipe/#article"
},
"mainEntityOfPage": "https://www.aspicyperspective.com/best-homemade-salsa-recipe/#webpage",
"url": "https://www.aspicyperspective.com/best-homemade-salsa-recipe/"
}

View file

@ -1,36 +0,0 @@
{
"image": "https://www.cookingforkeeps.com/wp-content/uploads/2013/02/done-1.jpg",
"aggregateRating": {
"properties": {
"ratingValue": "4.0",
"ratingCount": "2"
},
"@type": "AggregateRating"
},
"name": "Blue Cheese Stuffed Turkey Meatballs with Raspberry Balsamic Glaze",
"author": "Nicole-Cooking for Keeps",
"recipeYield": "Makes 18-22 meatballs depending on size",
"recipeInstructions": [
"For the meatballs: Roll the blue cheese in small balls about the diameter of a dime. Freeze for 30 minutes. Preheat oven to 375 degrees. Mix the remaining ingredients together, until just combined. Roll sausage mixture into small balls. Place the blue cheese in the middle, enclosing with meat. Bake on a silt pad until golden brown and cooked through, about 25 min, turning halfway through to ensure even browning.",
"For the Dipping Sauce:",
"Combine all ingredients together in small sauce pan over medium high heat. Bring to a boil and then reduce heat and simmer about five minutes. Coat meatballs in sauce. Serve."
],
"@context": "http://schema.org",
"@type": "Recipe",
"url": "https://www.cookingforkeeps.com/blue-cheese-stuffed-turkey-meatballs-with-raspberry-balsamic-glaze-2/",
"recipeIngredient": [
"Sausage Bites",
"3 oz creamy gorgonzola cheese",
"1 lb turkey Italian sausage (schmicas) with fennel seed",
"\u00bd cup Italian style bread crumbs",
"\u00bd onion grated",
"1 egg white",
"Salt to taste",
"Dipping Sauce:",
"\u00bd cup raspberry preserves",
"\u215b cup balsamic vinegar",
"3 teaspoons Dijon mustard",
"Pinch of red pepper",
"Pinch of Salt"
]
}

View file

@ -1,132 +0,0 @@
{
"@context": "http://schema.org",
"@type": "Recipe",
"articleBody": "Atlanta pastry chef Claudia Martinez\u2019s family has been making what Martinez describes as meaty Venezuelan tamales around the holidays for generations. In the Martinez household, every family member has a task: Claudia\u2019s dad or grandmother always prepares the guiso, the tender shredded chicken and beef stew that comprises the bulk of the filling. One person slicks scoops of vibrant orange achiote-stained masa dough onto banana leaves, then passes them around the table to get filled. Claudia\u2019s grandma adds a spoonful of guiso; Claudia adds olives and capers; her sister adds a few raisins. Finally, each hallaca gets wrapped up in the fragrant leaves and tied with twine like a tiny present, ready to boil for a late Christmas Eve dinner. The Martinez family usually makes 100 at a time; this scaled-down version of their recipe makes just under 20, enough for a big dinner plus leftovers you can freeze for another day. If you find yourself with leftover masa and stew, do as the Martinezes do: Make arepas with guiso and fried eggs for breakfast on Christmas Day. (If you\u2019re in Atlanta in the days leading up to Christmas Eve, pick up hallacas at Caf\u00e9 Claudia, the pop-up Martinez runs out of the Hotel Clermont.)\nBanana leaves give a floral and grassy flavor to the hallacas, you can buy them either fresh or frozen at Latin and Asian markets. You can use parchment paper instead, but the outcome won\u2019t be as complex.",
"alternativeHeadline": "The Venezuelan holiday dish that Atlanta pastry chef Claudia Martinez\u2019s family has been making for generations.",
"dateModified": "2021-01-02 12:09:30.443000",
"datePublished": "2020-12-01 07:00:00",
"keywords": [
"recipes",
"holiday 2020",
"new years eve",
"olive oil",
"beef",
"chicken recipes",
"kosher salt",
"tomato",
"garlic",
"tomato paste",
"onion",
"bell pepper",
"green onion scallion",
"cilantro",
"brown sugar",
"cornmeal",
"capers",
"olive",
"raisin",
"web"
],
"thumbnailUrl": "https://assets.bonappetit.com/photos/5fb4407993a08c9bf97163f7/1:1/w_1125,h_1125,c_limit/1220-Hallacas.jpg",
"publisher": {
"@context": "https://schema.org",
"@type": "Organization",
"name": "Bon App\u00e9tit",
"logo": {
"@type": "ImageObject",
"url": "https://www.bonappetit.com/verso/static/bon-appetit/assets/logo-seo.328de564b950e3d5d1fbe3e42f065290ca1d3844.png",
"width": "479px",
"height": "100px"
},
"url": "https://www.bonappetit.com"
},
"isPartOf": {
"@type": [
"CreativeWork",
"Product"
],
"name": "Bon App\u00e9tit"
},
"isAccessibleForFree": true,
"author": [
{
"@type": "Person",
"name": "Claudia Martinez",
"sameAs": "https://bon-appetit.com/contributor/claudia-martinez/"
}
],
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": 5,
"ratingCount": 22
},
"description": "The Venezuelan holiday dish that Atlanta pastry chef Claudia Martinez\u2019s family has been making for generations.",
"image": "hallacas.jpg",
"name": "Hallacas",
"recipeIngredient": [
"1\u00bd cups extra-virgin olive oil",
"3 Tbsp. plus 1\u00bd tsp. achiote (annatto) seeds",
"2\u00bd lb. boneless beef chuck roast",
"2\u00bd lb. skinless, boneless chicken breasts",
"1 Tbsp. Diamond Crystal or 1\u00be tsp. Morton kosher salt, plus more",
"3 medium tomatoes, coarsely chopped",
"3 garlic cloves",
"1 6-oz. can tomato paste",
"1 medium onion, chopped",
"1 large red bell pepper, seeds and ribs removed, coarsely chopped",
"1 large green bell pepper, seeds and ribs removed, coarsely chopped",
"1 bunch scallions, coarsely chopped",
"1 bunch cilantro, coarsely chopped",
"\u00bc cup (packed) light brown sugar",
"1 1-kg package P.A.N. precooked cornmeal",
"2 Tbsp. Diamond Crystal or 1 Tbsp. plus \u00bd tsp. kosher salt",
"3 1-lb. packages fresh or frozen, thawed banana or plantain leaves",
"\u00bc cup extra-virgin olive oil",
"\u00bd cup drained capers",
"\u00bd cup pitted green olives",
"\u00bd cup raisins"
],
"recipeInstructions": [
{
"@type": "HowToStep",
"text": "Cook oil and achiote seeds in a small saucepan over medium-low heat until oil turns deep orange, about 10 minutes. Strain into a heatproof jar and let cool. Measure out \u00bd cup achiote oil for making filling; set remaining 1 cup oil aside for making dough."
},
{
"@type": "HowToStep",
"text": "Bring beef, chicken, 1 Tbsp. Diamond Crystal or 1\u00be tsp. Morton kosher salt, and 12 cups water to a boil in a large pot over medium-high heat. Reduce heat to medium-low and let simmer until cooked through, about 30 minutes. Transfer beef and chicken to a cutting board and let sit until cool enough to handle. Pour 8 cups cooking liquid into a heatproof pitcher or large measuring glass; set aside. Discard any extra liquid."
},
{
"@type": "HowToStep",
"text": "Cut beef and chicken into \u2153\" cubes; place back into pot (cooking the meat before you chop it means that you can cut the pieces finer and more evenly). Blend tomatoes, garlic, and tomato paste in a blender until smooth; scrape pur\u00e9e into pot with meat. Blend onion, red and green bell peppers, scallions, cilantro, and \u00bd cup reserved cooking liquid in blender until smooth and add to pot. Add brown sugar and \u00bd cup reserved achiote oil. Pour in remaining 7\u00bd cups reserved cooking liquid. Bring to a boil, then reduce heat to medium-low and simmer until meat is tender and liquid is slightly reduced, about 40 minutes. Drain meat in a colander, season lightly with salt, and let cool."
},
{
"@type": "HowToStep",
"text": "Meanwhile, mix cornmeal, salt, reserved 1 cup achiote oil, and 8 cups water in a large bowl with your hands until dough is smooth, spreadable, and no large lumps remain, 5\u20137 minutes. Press a sheet of plastic wrap or parchment paper directly onto surface of dough; let rest at least 30 minutes or up to 1 hour."
},
{
"@type": "HowToStep",
"text": "Wash and pat banana leaves dry. Carefully remove any center stems with kitchen shears, avoiding breaking through the leaf, then cut into 14x10\" rectangles. Mix oil and 1 cup water in a medium bowl (it needs to be big enough to dip your hands into). This will help to keep the dough from sticking to your hands. Working one at a time, place a banana leaf on a surface so the veins in the leaves run horizontally. Dipping your hands in oil mixture as you work, place \u00be cup dough in center of leaf and spread out with your fingers into a \u215b\"-thick rectangle, leaving a 1\" border near the vertical edges and a space on both horizontal edges. Place \u00be cup guiso into center of dough. Top with 5 capers, 2 olives, and 8 raisins."
},
{
"@type": "HowToStep",
"text": "Take top and bottom edges of leaf and bring up toward each other so edges of dough meet and enclose filling. Pull both sides of banana leaf together snugly toward the upper edge of hallaca to seal and fold over toward you to make a tube. Fold remaining 2 side ends toward the center to make a small package."
},
{
"@type": "HowToStep",
"text": "Place package, fold side down, on another banana leaf and wrap up again. Wrap once more in a third leaf to hold everything together, then tie closed with kitchen twine. (Make sure package is compact, the leaves are not ripped, and hallaca is not leaking.) Repeat with remaining dough, filling, and banana leaves."
},
{
"@type": "HowToStep",
"text": "Place as many hallacas as will fit into a clean large pot, pour in water to cover, and bring to a boil. Reduce heat and simmer, turning hallacas halfway through, until plumped and firm, about 35 minutes. Repeat with remaining hallacas.\nDo ahead: Hallacas can be made 1 week ahead. Let cool, then cover and chill, or freeze up to 3 months. To reheat, cook in a pot of simmering water (make sure hallacas are submerged), partially covered, until warmed through, 10\u201315 minutes if chilled, 25\u201330 minutes if frozen."
}
],
"recipeYield": "Makes about 18",
"url": "https://www.bonappetit.com/recipe/hallacas",
"slug": "hallacas",
"orgURL": "https://www.bonappetit.com/recipe/hallacas",
"categories": [],
"tags": [],
"dateAdded": null,
"notes": [],
"extras": []
}

View file

@ -1,33 +0,0 @@
{
"url": "https://www.deliaonline.com/recipes/seasons/what-should-you-be-cooking-in-november/chunky-apple-cake",
"author": "Delia Smith",
"image": "https://www.deliaonline.com/sites/default/files/quick_media/cakes-chunky-apple-cake.jpg",
"name": "Chunky Apple Cake",
"description": "Apples are superb in cakes, so in the autumn when there are lots of windfalls around, why not make a few of these and freeze them.",
"recipeCuisine": "General",
"recipeCategory": [
"Apples",
"Afternoon Tea",
"Cake Recipes",
"Autumn",
"Life in the Freezer"
],
"keywords": "Apples, Afternoon Tea, Cake Recipes, Autumn, Life in the Freezer, Delia, Delia Smith",
"recipeInstructions": "Begin by sifting the flour, baking powder and spices into a roomy mixing bowl, lifting the sieve quite high to give the flour a good airing as it goes down.\n\nNext chop the apples into small dice (with or without peel, just as you like). Then place them in a bowl and toss them with one tablespoon of the sieved flour mixture. Then add the eggs, butter and sugar to the rest of the flour, and using an electric hand whisk, combine them for about 1 minute until you have a smooth creamy consistency. After that fold in the grated orange zest, mixed peel and diced apple. If the mixture seems a little dry, add a tablespoon of milk. Now spoon the cake mix into the prepared tin and level it off with the back of a spoon.\n\nThen bake near the centre of the oven for about one hour or until the cake feels springy in the centre when lightly pressed with a fingertip and just shows signs of shrinking away from the edge of the tin. Cool in the tin for 10 minutes before turning out onto a wire rack. This looks nice dusted with sifted icing sugar just before serving. Store in an airtight tin.\n\nYou can watch more of Delia's cake recipes being made in our Cookery School Videos on the right.",
"recipeIngredient": [
"225g self-raising flour",
"1 rounded teaspoon baking powder",
"1 level teaspoon mixed spice",
"\u00bd level teaspoon ground cinnamon",
"3 Bramley apples (about 550g)",
"2 large eggs, beaten",
"75g spreadable butter",
"175g light brown soft sugar",
"grated zest of 1 large orange",
"1 tablespoon chopped mixed peel",
"1 tablespoon milk (if needed)",
"little icing sugar"
],
"@context": "http://schema.org",
"@type": "Recipe"
}

View file

@ -1,102 +0,0 @@
{
"@context": "http://schema.org/",
"@type": "Recipe",
"name": "Dairy-Free Impossible Pumpkin Pie",
"author": {
"@type": "Person",
"name": "Kare for Kitchen Treaty"
},
"description": "This crustless pumpkin pie might just be the\u00a0easiest\u00a0you'll ever make. Simply blend the ingredients together, pour into your pie pan, and bake!",
"datePublished": "2017-11-10T16:12:06+00:00",
"image": [
"https://www.kitchentreaty.com/wp-content/uploads/2017/11/dairy-free-impossible-pumpkin-pie-8.jpg"
],
"recipeYield": [
"8"
],
"prepTime": "PT10M",
"cookTime": "PT45M",
"totalTime": "PT55M",
"recipeIngredient": [
"1 (15-ounce) can coconut milk (I recommend full-fat for a richer pie, but lite also works)",
"1 cup pumpkin puree",
"4 large eggs",
"1/2 cup granulated sugar",
"1 tablespoon pure vanilla extract",
"1/2 cup all-purpose flour (or your favorite cup-for-cup gluten-free flour blend*)",
"1 teaspoon baking powder",
"1 tablespoon pumpkin pie spice",
"1/2 teaspoon fine-grain sea salt or table salt",
"Coconut whipped cream (for serving**)"
],
"recipeInstructions": [
{
"@type": "HowToStep",
"text": "Preheat oven to 375 degrees Fahrenheit and position rack in the middle of the oven. Spray a 9- or 10-inch pie pan with baking spray or oil the pan with coconut oil or vegan butter.",
"name": "Preheat oven to 375 degrees Fahrenheit and position rack in the middle of the oven. Spray a 9- or 10-inch pie pan with baking spray or oil the pan with coconut oil or vegan butter.",
"url": "https://www.kitchentreaty.com/dairy-free-impossible-pumpkin-pie/#wprm-recipe-32856-step-0-0"
},
{
"@type": "HowToStep",
"text": "Add the coconut milk, pumpkin, eggs, sugar, and vanilla to the pitcher of a blender. Blend until combined, about 20 seconds. Add the flour, baking powder, pumpkin pie spice, and salt. Blend again until well-combined, another 20\u00a0seconds.",
"name": "Add the coconut milk, pumpkin, eggs, sugar, and vanilla to the pitcher of a blender. Blend until combined, about 20 seconds. Add the flour, baking powder, pumpkin pie spice, and salt. Blend again until well-combined, another 20\u00a0seconds.",
"url": "https://www.kitchentreaty.com/dairy-free-impossible-pumpkin-pie/#wprm-recipe-32856-step-0-1"
},
{
"@type": "HowToStep",
"text": "Pour filling into the pie plate. The mixture will be fairly runny. Carefully transfer to the preheated oven.",
"name": "Pour filling into the pie plate. The mixture will be fairly runny. Carefully transfer to the preheated oven.",
"url": "https://www.kitchentreaty.com/dairy-free-impossible-pumpkin-pie/#wprm-recipe-32856-step-0-2"
},
{
"@type": "HowToStep",
"text": "Bake\u00a0until the middle just barely jiggles, 40-50 minutes. I like to check the middle by giving the pie pan a little nudge, and if it seems like it's no longer liquid, I'll pull the pie out and insert a butter knife about halfway between the center and the edge. If the knife comes out relatively clean - no runny pie filling - it's\u00a0done!",
"name": "Bake\u00a0until the middle just barely jiggles, 40-50 minutes. I like to check the middle by giving the pie pan a little nudge, and if it seems like it's no longer liquid, I'll pull the pie out and insert a butter knife about halfway between the center and the edge. If the knife comes out relatively clean - no runny pie filling - it's\u00a0done!",
"url": "https://www.kitchentreaty.com/dairy-free-impossible-pumpkin-pie/#wprm-recipe-32856-step-0-3"
},
{
"@type": "HowToStep",
"text": "Place on a cooling rack and let cool, about 1 hour. Transfer to refrigerator to completely\u00a0cool, at least one more hour (or up to 3 days in advance).",
"name": "Place on a cooling rack and let cool, about 1 hour. Transfer to refrigerator to completely\u00a0cool, at least one more hour (or up to 3 days in advance).",
"url": "https://www.kitchentreaty.com/dairy-free-impossible-pumpkin-pie/#wprm-recipe-32856-step-0-4"
},
{
"@type": "HowToStep",
"text": "If desired, top pie with dollops of coconut whipped cream. Or simply cut slices, transfer to a plate, and top\u00a0individual servings with the whipped cream.",
"name": "If desired, top pie with dollops of coconut whipped cream. Or simply cut slices, transfer to a plate, and top\u00a0individual servings with the whipped cream.",
"url": "https://www.kitchentreaty.com/dairy-free-impossible-pumpkin-pie/#wprm-recipe-32856-step-0-5"
},
{
"@type": "HowToStep",
"text": "Keeps in the refrigerator for 3-4 days. I suggest covering the completely cooled pie with plastic wrap if not serving right away.",
"name": "Keeps in the refrigerator for 3-4 days. I suggest covering the completely cooled pie with plastic wrap if not serving right away.",
"url": "https://www.kitchentreaty.com/dairy-free-impossible-pumpkin-pie/#wprm-recipe-32856-step-0-6"
}
],
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "5",
"ratingCount": "4"
},
"recipeCategory": [
"Dessert"
],
"recipeCuisine": [
"American"
],
"keywords": "pie",
"nutrition": {
"@type": "NutritionInformation",
"calories": "231 kcal",
"sugarContent": "14 g",
"sodiumContent": "239 mg",
"fatContent": "14 g",
"saturatedFatContent": "11 g",
"carbohydrateContent": "23 g",
"fiberContent": "1 g",
"proteinContent": "5 g",
"cholesterolContent": "82 mg",
"servingSize": "1 serving"
},
"url": "https://www.kitchentreaty.com/dairy-free-impossible-pumpkin-pie/"
}

View file

@ -1,121 +0,0 @@
{
"@context": "http://schema.org/",
"@type": "Recipe",
"name": "How to Make Instant Pot Spaghetti",
"author": {
"@type": "Person",
"name": "Karlynn Johnston"
},
"description": "This Instant Pot Spaghetti recipe is literally the best one out there and it's thanks to one ( or two!) secret ingredients!",
"datePublished": "2020-09-15T13:00:52+00:00",
"image": [
"https://www.thekitchenmagpie.com/wp-content/uploads/images/2018/02/instantpotspaghetti.jpg",
"https://www.thekitchenmagpie.com/wp-content/uploads/images/2018/02/instantpotspaghetti-500x500.jpg",
"https://www.thekitchenmagpie.com/wp-content/uploads/images/2018/02/instantpotspaghetti-500x375.jpg",
"https://www.thekitchenmagpie.com/wp-content/uploads/images/2018/02/instantpotspaghetti-480x270.jpg"
],
"recipeYield": [
"4"
],
"prepTime": "PT15M",
"cookTime": "PT7M",
"totalTime": "PT22M",
"recipeIngredient": [
"1 tablespoon olive oil",
"1 cup white onion (diced)",
"1 tablespoon fresh minced garlic",
"1 pound lean ground beef",
"2 teaspoons Italian seasoning mix",
"one 16 ounce package uncooked white flour spaghetti noodles (cooking time for al dente needs to be 9-10 minutes! )",
"one 750 millilitre jar of 4 cheese spaghetti sauce",
"one 15 ounce can diced tomatoes",
"3 cups weak beef broth (divided)",
"1/2 teaspoon salt (( to taste))",
"1/2 teaspoon black pepper",
"1/2 teaspoon white sugar (to cut the acidity of the tomatoes )"
],
"recipeInstructions": [
{
"@type": "HowToStep",
"text": "Press the \"saute\" button on your Instant Pot. Add in the olive oil and heat. Once it's heated, add in the white onion. Saute until the onion is soft and translucent. Add in the garlic and fry for 2-3 minutes.",
"name": "Press the \"saute\" button on your Instant Pot. Add in the olive oil and heat. Once it's heated, add in the white onion. Saute until the onion is soft and translucent. Add in the garlic and fry for 2-3 minutes.",
"url": "https://www.thekitchenmagpie.com/how-to-make-instant-pot-spaghetti/#wprm-recipe-44488-step-0-0",
"image": "https://www.thekitchenmagpie.com/wp-content/uploads/images/2018/02/fryinggroundbeefandonionsinaninsantpot.jpg"
},
{
"@type": "HowToStep",
"text": "Add in the ground beef and fry , stirring constantly, until it's no longer pink. Press the Cancel button to turn off the Instant Pot heating element. Drain the fat (keeping some for flavour if wanted).",
"name": "Add in the ground beef and fry , stirring constantly, until it's no longer pink. Press the Cancel button to turn off the Instant Pot heating element. Drain the fat (keeping some for flavour if wanted).",
"url": "https://www.thekitchenmagpie.com/how-to-make-instant-pot-spaghetti/#wprm-recipe-44488-step-0-1"
},
{
"@type": "HowToStep",
"text": "Add in 1 cup of the beef broth, mixing it in with the ground beef on the bottom.",
"name": "Add in 1 cup of the beef broth, mixing it in with the ground beef on the bottom.",
"url": "https://www.thekitchenmagpie.com/how-to-make-instant-pot-spaghetti/#wprm-recipe-44488-step-0-2"
},
{
"@type": "HowToStep",
"text": "Break the spaghetti noodles in half. Place in random, different criss-cross patterns on top of the beef/ beef broth mixture. You are trying to created space between the noodles to try and prevent sticking.",
"name": "Break the spaghetti noodles in half. Place in random, different criss-cross patterns on top of the beef/ beef broth mixture. You are trying to created space between the noodles to try and prevent sticking.",
"url": "https://www.thekitchenmagpie.com/how-to-make-instant-pot-spaghetti/#wprm-recipe-44488-step-0-3",
"image": "https://www.thekitchenmagpie.com/wp-content/uploads/images/2018/02/howtobreakspaghettinoodlesfortheinstantpot.jpg"
},
{
"@type": "HowToStep",
"text": "In a large bowl or large glass spouted measuring glass, combine the remaining beef broth, tomatoes, 4 cheese sauce, Italian seasoning, salt, pepper and dash of white sugar. ",
"name": "In a large bowl or large glass spouted measuring glass, combine the remaining beef broth, tomatoes, 4 cheese sauce, Italian seasoning, salt, pepper and dash of white sugar. ",
"url": "https://www.thekitchenmagpie.com/how-to-make-instant-pot-spaghetti/#wprm-recipe-44488-step-0-4"
},
{
"@type": "HowToStep",
"text": "Pout the liquid mixture on top of the pasta, around the sides, making sure you coat everything. Take a wooden spoon and gently push down on the spaghetti noodles, making sure that they are all underneath the liquid.",
"name": "Pout the liquid mixture on top of the pasta, around the sides, making sure you coat everything. Take a wooden spoon and gently push down on the spaghetti noodles, making sure that they are all underneath the liquid.",
"url": "https://www.thekitchenmagpie.com/how-to-make-instant-pot-spaghetti/#wprm-recipe-44488-step-0-5"
},
{
"@type": "HowToStep",
"text": "Press the Manual Button ( you are going to use high pressure) and set for 7 minutes. Listen to make sure that it seals.",
"name": "Press the Manual Button ( you are going to use high pressure) and set for 7 minutes. Listen to make sure that it seals.",
"url": "https://www.thekitchenmagpie.com/how-to-make-instant-pot-spaghetti/#wprm-recipe-44488-step-0-6"
},
{
"@type": "HowToStep",
"text": "When it's done, release the valve manually ( see the link in my suggestions in the post above). Stir the spaghetti, breaking up any noodles that stuck together. Let it sit for a few minutes, soaking up the extra liquid.",
"name": "When it's done, release the valve manually ( see the link in my suggestions in the post above). Stir the spaghetti, breaking up any noodles that stuck together. Let it sit for a few minutes, soaking up the extra liquid.",
"url": "https://www.thekitchenmagpie.com/how-to-make-instant-pot-spaghetti/#wprm-recipe-44488-step-0-7",
"image": "https://www.thekitchenmagpie.com/wp-content/uploads/images/2018/02/instantpotspaghetti3.jpg"
}
],
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "5",
"ratingCount": "15"
},
"recipeCategory": [
"supper"
],
"recipeCuisine": [
"American"
],
"keywords": "Instant Pot Spaghetti",
"nutrition": {
"@type": "NutritionInformation",
"calories": "222 kcal",
"carbohydrateContent": "5 g",
"proteinContent": "27 g",
"fatContent": "9 g",
"saturatedFatContent": "3 g",
"cholesterolContent": "70 mg",
"sodiumContent": "699 mg",
"fiberContent": "1 g",
"sugarContent": "2 g",
"servingSize": "1 serving"
},
"@id": "https://www.thekitchenmagpie.com/how-to-make-instant-pot-spaghetti/#recipe",
"isPartOf": {
"@id": "https://www.thekitchenmagpie.com/how-to-make-instant-pot-spaghetti/#article"
},
"mainEntityOfPage": "https://www.thekitchenmagpie.com/how-to-make-instant-pot-spaghetti/#webpage",
"url": "https://www.thekitchenmagpie.com/how-to-make-instant-pot-spaghetti/"
}

View file

@ -1,82 +0,0 @@
{
"@context": "http://schema.org/",
"@type": "Recipe",
"name": "Instant Pot Chicken and Potatoes",
"author": {
"@type": "Person",
"name": "Tiffany"
},
"description": "This is hands down the BEST Instant Pot Chicken and Potatoes recipe you'll ever try. Juicy ranch-seasoned chicken breast and parmesan potatoes cooked in 30 minutes in your pressure cooker - it doesn't get easier than this! ",
"datePublished": "2018-10-26T07:00:51+00:00",
"image": [
"https://www.lecremedelacrumb.com/wp-content/uploads/2018/10/instant-pot-chicken-potatoes-2.jpg",
"https://www.lecremedelacrumb.com/wp-content/uploads/2018/10/instant-pot-chicken-potatoes-2-500x500.jpg",
"https://www.lecremedelacrumb.com/wp-content/uploads/2018/10/instant-pot-chicken-potatoes-2-500x375.jpg",
"https://www.lecremedelacrumb.com/wp-content/uploads/2018/10/instant-pot-chicken-potatoes-2-480x270.jpg"
],
"recipeYield": [
"4",
"4 people"
],
"prepTime": "PT10M",
"cookTime": "PT15M",
"totalTime": "PT40M",
"recipeIngredient": [
"4 boneless skinless chicken breasts",
"2 pounds baby red or gold potatoes",
"3 tablespoons olive oil",
"1 1/2 teaspoons salt (or to taste)",
"1/2 teaspoon pepper (or to taste)",
"1 teaspoon garlic powder",
"1 teaspoon dried thyme",
"1/2 teaspoon dried basil",
"1/2 teaspoon dried oregano",
"2 tablespoons + 2 teaspoons dry Ranch seasoning (divided)",
"1 cup chicken broth",
"3 tablespoons grated parmesan cheese"
],
"recipeInstructions": [
{
"@type": "HowToStep",
"text": "In a large bowl toss chicken and potatoes in the olive oil, then season with salt and pepper. Stir together garlic powder, thyme, basil, oregano, and 2 tablespoons of the Ranch seasoning. Sprinkle over the chicken and potatoes, tossing to distribute the ingredients as evenly as possible. ",
"name": "In a large bowl toss chicken and potatoes in the olive oil, then season with salt and pepper. Stir together garlic powder, thyme, basil, oregano, and 2 tablespoons of the Ranch seasoning. Sprinkle over the chicken and potatoes, tossing to distribute the ingredients as evenly as possible. ",
"url": "https://www.lecremedelacrumb.com/instant-pot-chicken-and-potatoes/#wprm-recipe-22284-step-0-0"
},
{
"@type": "HowToStep",
"text": "Add chicken broth to the instant pot/pressure cooker, then place chicken in the broth, and top with the potatoes. Place the lid on in the locked position and turn the vent to the sealed position. Set pressure cooker to \"pressure cook\" for 15 minutes.",
"name": "Add chicken broth to the instant pot/pressure cooker, then place chicken in the broth, and top with the potatoes. Place the lid on in the locked position and turn the vent to the sealed position. Set pressure cooker to \"pressure cook\" for 15 minutes.",
"url": "https://www.lecremedelacrumb.com/instant-pot-chicken-and-potatoes/#wprm-recipe-22284-step-0-1"
},
{
"@type": "HowToStep",
"text": "Once the cook time is finished, do a \"quick release\" by turning the vent to the venting position. Once float valve has dropped, remove the lid. Drain the pressure cooker or use a slotted spoon to transfer chicken and potatoes to a large platter. ",
"name": "Once the cook time is finished, do a \"quick release\" by turning the vent to the venting position. Once float valve has dropped, remove the lid. Drain the pressure cooker or use a slotted spoon to transfer chicken and potatoes to a large platter. ",
"url": "https://www.lecremedelacrumb.com/instant-pot-chicken-and-potatoes/#wprm-recipe-22284-step-0-2"
},
{
"@type": "HowToStep",
"text": "Sprinkle with Ranch seasoning and parmesan cheese and garnish with chopped thyme or parsley if desired before serving. ",
"name": "Sprinkle with Ranch seasoning and parmesan cheese and garnish with chopped thyme or parsley if desired before serving. ",
"url": "https://www.lecremedelacrumb.com/instant-pot-chicken-and-potatoes/#wprm-recipe-22284-step-0-3"
}
],
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.76",
"ratingCount": "225"
},
"recipeCategory": [
"Main Course"
],
"recipeCuisine": [
"American"
],
"keywords": "Chicken, healthy, instant pot, mashed potatoes, pressure cooker, ranch",
"@id": "https://www.lecremedelacrumb.com/instant-pot-chicken-and-potatoes/#recipe",
"isPartOf": {
"@id": "https://www.lecremedelacrumb.com/instant-pot-chicken-and-potatoes/#article"
},
"mainEntityOfPage": "https://www.lecremedelacrumb.com/instant-pot-chicken-and-potatoes/#webpage",
"url": "https://www.lecremedelacrumb.com/instant-pot-chicken-and-potatoes/"
}

View file

@ -1,166 +0,0 @@
{
"@context": "http://schema.org/",
"@type": "Recipe",
"name": "How to make Instant Pot Kerala Vegetable Stew",
"author": {
"@type": "Person",
"name": "Dhwani"
},
"description": "Instant Pot Kerala Vegetable Stew - A complete Comfort and Satisfying food that can be made in a fraction of the time. Veg Stew is Vegetarian / Vegan Instant Pot Recipe with lots of vegetables in coconut milk based hearty sauce that will change your life.",
"datePublished": "2019-01-16T19:25:09+00:00",
"image": [
"https://cdn.cookingcarnival.com/wp-content/uploads/2019/01/Instant-Pot-Kerala-Vegetable-Stew-2.jpg",
"https://cdn.cookingcarnival.com/wp-content/uploads/2019/01/Instant-Pot-Kerala-Vegetable-Stew-2-500x500.jpg",
"https://cdn.cookingcarnival.com/wp-content/uploads/2019/01/Instant-Pot-Kerala-Vegetable-Stew-2-500x375.jpg",
"https://cdn.cookingcarnival.com/wp-content/uploads/2019/01/Instant-Pot-Kerala-Vegetable-Stew-2-480x270.jpg"
],
"video": {
"name": "Instant Pot Kerala Vegetable Stew | Vegan stew recipe | vegetable Stew recipe in instant Pot",
"description": "Instant Pot Kerala Vegetable Stew - A complete Comfort and Satisfying food that can be made in a fraction of the time. Veg Stew is Vegetarian / Vegan Instant Pot Recipe with lots of vegetables in coconut milk based hearty sauce that will change your life.\n\nDetailed Recipe of Instant pot Kerela vegetable stew https://www.cookingcarnival.com/instant-pot-kerala-vegetable-stew/\nOfficial Facebook Page: https://www.facebook.com/cookingcarnival\n\nPinterest: https://www.pinterest.com/cookingcarnival/\n\nTwitter: https://twitter.com/carnivalcooking\n\nGoogle Plus: https://plus.google.com/+Cookingcarnival\n\nInstagram: https://www.instagram.com/cookingcarnival",
"uploadDate": "2019-01-17T19:46:14+00:00",
"duration": "PT2M17S",
"thumbnailUrl": "https://i.ytimg.com/vi/pej98AtiBWE/hqdefault.jpg",
"contentUrl": "https://youtu.be/pej98AtiBWE",
"embedUrl": "https://www.youtube.com/embed/pej98AtiBWE?feature=oembed",
"@type": "VideoObject"
},
"recipeYield": [
"4",
"4 people"
],
"prepTime": "PT10M",
"cookTime": "PT10M",
"totalTime": "PT20M",
"recipeIngredient": [
"2 cups - Cauliflower florets",
"1 cup - Chopped carrots",
"1 1/2 cup - Bell Peppers (chopped)",
"2 cups - Potatoes (Chopped)",
"3/4 cup - Chopped Onions",
"1 cup - Green beans (Chopped)",
"1 tsp - Ginger paste",
"1/2 tsp - Chili ((adust according to your liking) )",
"1 tsp - Garlic paste",
"2 - Cardamom Pods (See Notes)",
"1 inch - Cinnamon stick",
"3 - Cloves",
"20 Pieces - Whole Cashew Nuts",
"1 cup - Coconut milk (See Notes)",
"Salt to taste",
"1/2 tsp - White Pepper Powder (see notes)",
"2 tbsp - Oil (See Notes)",
"2 cups - Water"
],
"recipeInstructions": [
{
"@type": "HowToStep",
"text": "Turn on saute button of your IP.",
"name": "Turn on saute button of your IP.",
"url": "https://www.cookingcarnival.com/instant-pot-kerala-vegetable-stew/#wprm-recipe-8126-step-0-0"
},
{
"@type": "HowToStep",
"text": "Heat oil in a pot, add cardamom pods, cinnamon stick, and cloves.",
"name": "Heat oil in a pot, add cardamom pods, cinnamon stick, and cloves.",
"url": "https://www.cookingcarnival.com/instant-pot-kerala-vegetable-stew/#wprm-recipe-8126-step-0-1"
},
{
"@type": "HowToStep",
"text": "Now add ginger, garlic, chili and onions. Saute for few seconds.",
"name": "Now add ginger, garlic, chili and onions. Saute for few seconds.",
"url": "https://www.cookingcarnival.com/instant-pot-kerala-vegetable-stew/#wprm-recipe-8126-step-0-2"
},
{
"@type": "HowToStep",
"text": "Add all the vegetables, salt, white pepper powder and water. Mix well.",
"name": "Add all the vegetables, salt, white pepper powder and water. Mix well.",
"url": "https://www.cookingcarnival.com/instant-pot-kerala-vegetable-stew/#wprm-recipe-8126-step-0-3"
},
{
"@type": "HowToStep",
"text": "Cover your Instant pot with locking lid.",
"name": "Cover your Instant pot with locking lid.",
"url": "https://www.cookingcarnival.com/instant-pot-kerala-vegetable-stew/#wprm-recipe-8126-step-0-4"
},
{
"@type": "HowToStep",
"text": "Turn off IP.",
"name": "Turn off IP.",
"url": "https://www.cookingcarnival.com/instant-pot-kerala-vegetable-stew/#wprm-recipe-8126-step-0-5"
},
{
"@type": "HowToStep",
"text": "Press the manual or pressure cook button. Cook on high pressure for 3 minutes with pressure valve in the sealing position.",
"name": "Press the manual or pressure cook button. Cook on high pressure for 3 minutes with pressure valve in the sealing position.",
"url": "https://www.cookingcarnival.com/instant-pot-kerala-vegetable-stew/#wprm-recipe-8126-step-0-6"
},
{
"@type": "HowToStep",
"text": "Meanwhile, take whole cashew and coconut milk in a blender jar and blend them well in to a smooth paste. Keep it aside.",
"name": "Meanwhile, take whole cashew and coconut milk in a blender jar and blend them well in to a smooth paste. Keep it aside.",
"url": "https://www.cookingcarnival.com/instant-pot-kerala-vegetable-stew/#wprm-recipe-8126-step-0-7"
},
{
"@type": "HowToStep",
"text": "Once IP beeps and when you see LO:00, turn off your IP and quick release the pressure.",
"name": "Once IP beeps and when you see LO:00, turn off your IP and quick release the pressure.",
"url": "https://www.cookingcarnival.com/instant-pot-kerala-vegetable-stew/#wprm-recipe-8126-step-0-8"
},
{
"@type": "HowToStep",
"text": "10. Open the Instant Pot, add prepared cashew-coconut paste. Stir well.",
"name": "10. Open the Instant Pot, add prepared cashew-coconut paste. Stir well.",
"url": "https://www.cookingcarnival.com/instant-pot-kerala-vegetable-stew/#wprm-recipe-8126-step-0-9"
},
{
"@type": "HowToStep",
"text": "11. Turn on saute button and cook it for 1 to 2 more minutes, until everything well combined.",
"name": "11. Turn on saute button and cook it for 1 to 2 more minutes, until everything well combined.",
"url": "https://www.cookingcarnival.com/instant-pot-kerala-vegetable-stew/#wprm-recipe-8126-step-0-10"
},
{
"@type": "HowToStep",
"text": "12. Switch off the IP.",
"name": "12. Switch off the IP.",
"url": "https://www.cookingcarnival.com/instant-pot-kerala-vegetable-stew/#wprm-recipe-8126-step-0-11"
},
{
"@type": "HowToStep",
"text": "13. Instant Pot Kerala Vegetable Stew is ready. Enjoy!!",
"name": "13. Instant Pot Kerala Vegetable Stew is ready. Enjoy!!",
"url": "https://www.cookingcarnival.com/instant-pot-kerala-vegetable-stew/#wprm-recipe-8126-step-0-12"
}
],
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.88",
"ratingCount": "8"
},
"recipeCategory": [
"Main Course",
"Soups and Stew"
],
"recipeCuisine": [
"American",
"Indian"
],
"keywords": "Easy vegan instant pot recipe, Instant pot, Vegetable Stew",
"nutrition": {
"@type": "NutritionInformation",
"servingSize": "1 person",
"calories": "201 kcal",
"carbohydrateContent": "24 g",
"proteinContent": "4 g",
"fatContent": "10 g",
"saturatedFatContent": "1 g",
"sodiumContent": "56 mg",
"fiberContent": "5 g",
"sugarContent": "9 g"
},
"@id": "https://www.cookingcarnival.com/instant-pot-kerala-vegetable-stew/#recipe",
"isPartOf": {
"@id": "https://www.cookingcarnival.com/instant-pot-kerala-vegetable-stew/#article"
},
"mainEntityOfPage": "https://www.cookingcarnival.com/instant-pot-kerala-vegetable-stew/#webpage",
"url": "https://www.cookingcarnival.com/instant-pot-kerala-vegetable-stew/"
}

View file

@ -1,53 +0,0 @@
{
"@context": "https://schema.org",
"@type": "Recipe",
"aggregateRating": {
"ratingCount": 3,
"ratingValue": 4
},
"author": {
"@type": "Person",
"name": "Justine Pattison"
},
"cookTime": "PT10M",
"description": "Microwave jacket sweet potatoes make a wonderfully quick and easy meal. Take your pick of these three delicious fillings, or make all of them! The veggie chilli makes enough for four portions, great for lunch tomorrow. The smoked mackerel and pea fillings each make enough for two portions. \r\n\r\nThis recipe was tested using a 900W microwave oven. If your oven has more or fewer watts, you will need to adjust the cooking time.\r\n",
"image": [
"https://food-images.files.bbci.co.uk/food/recipes/microwave_sweet_potatoes_04783_16x9.jpg"
],
"keywords": "quick, jacket potato dinners, microwave recipes , quick and cheap dinners, quick delicious lunches, easy family dinners, lunch, student food, Jacket potato, sweet potato, peas, egg free, gluten free, nut free, pregnancy friendly",
"name": "Microwave jacket sweet potato ",
"prepTime": "PT30M",
"recipeCategory": "Main course",
"recipeIngredient": [
"2 sweet potatoes, washed and dried",
"75g/2\u00bdoz smoked mackerel, skinned and roughly mashed with a fork",
"3 tbsp half-fat cr\u00e8me fra\u00eeche or soured cream",
"2 spring onions, trimmed and thinly sliced",
"\u00bd unwaxed lemon, finely grated zest only",
"freshly ground black pepper ",
"100g/3\u00bdoz frozen peas",
"100g/3\u00bdoz feta ",
"2 tbsp plain yoghurt",
"1 tbsp finely chopped fresh mint",
"freshly ground black pepper ",
"\u00bd red pepper, deseeded and diced",
"400g tin kidney beans in chilli sauce",
"198g tin sweetcorn in water",
"1 tbsp fresh lime juice",
"50g/1\u00beoz mature Cheddar, coarsely grated",
"4 tbsp soured cream",
"fresh coriander, to garnish",
"1 lime, cut into wedges, to serve"
],
"recipeInstructions": [
"Prick the sweet potatoes two or three times with a fork and put on a microwaveable plate. Microwave on high for 5\u20136 minutes for one potato or 7\u20138 minutes for two. Test the potatoes are soft by inserting a skewer through the middle, it should slide in easily. If the potatoes remain a little hard, cook for longer, testing again every 30 seconds. Divide the potatoes between plates, make a cross in the centre and open to fill.",
"To make the smoked mackerel filling, mix all the ingredients together and season with lots of black pepper.",
"To make the pea and feta filling, microwave the peas on high for 2\u20133 minutes, until thawed and just warm. Mash them with a fork, until well broken up, then mix in the feta, yoghurt and mint. Season with lots of black pepper.",
"To make the veggie chilli filling, put the red pepper in a large microwavable bowl and cook on high for 1\u00bd\u20132 minutes, until soft. Add the beans and sweetcorn in its water, stir well and microwave on high for 4\u20135 minutes, until hot. Stir in the lime juice and mix well. Spoon into the cooked sweet potatoes and top with the cheese. Microwave for 1\u20132 minutes, until the cheese melts. Top with the soured cream, coriander and lime wedges. "
],
"recipeYield": "Serves 2",
"suitableForDiet": [
"http://schema.org/GlutenFreeDiet"
],
"url": "https://www.bbc.co.uk/food/recipes/microwave_sweet_potatoes_04783"
}

View file

@ -1,243 +0,0 @@
{
"@context": "http://schema.org",
"@type": "Recipe",
"mainEntityOfPage": "http://www.eatingwell.com/recipe/249961/moroccan-skirt-steak-with-roasted-pepper-couscous/",
"name": "Moroccan Skirt Steak with Roasted Pepper Couscous",
"image": {
"@type": "ImageObject",
"url": "https://imagesvc.meredithcorp.io/v3/mm/image?url=https%3A%2F%2Fstatic.onecms.io%2Fwp-content%2Fuploads%2Fsites%2F44%2F2019%2F08%2F26231251%2F3757257.jpg",
"width": 960,
"height": 960
},
"datePublished": "2016-06-03T04:27:31.000Z",
"description": "Thin cuts of beef, such as skirt steak or sirloin steak, cook very quickly when seared in a hot skillet--just right for a busy weeknight. We love how the spicy Moroccan flavors on the steak complement the sweet, roasted pepper-studded couscous. Serve with: Arugula salad and a glass of Pinot Noir.",
"prepTime": null,
"cookTime": null,
"totalTime": "P0DT0H35M",
"recipeIngredient": [
"2 medium bell peppers",
"1 teaspoon ground cumin",
"1 teaspoon ground coriander",
"\u00be teaspoon salt",
"\u00bd teaspoon ground turmeric",
"\u00bd teaspoon ground cinnamon",
"\u00bd teaspoon freshly ground pepper",
"1 whole lemon, plus more lemon wedges for garnish",
"1 tablespoon 1 teaspoon plus 1 tablespoon extra-virgin olive oil, divided",
"\u2154 cup whole-wheat couscous",
"1 pound 1 pound skirt steak (see Note) or sirloin steak, 3/4 to 1 inch thick, trimmed",
"2 tablespoons chopped green olives"
],
"recipeInstructions": [
{
"@type": "HowToStep",
"text": "Position rack in upper third of oven; preheat broiler.\n"
},
{
"@type": "HowToStep",
"text": "Place bell peppers on a baking sheet and roast under the broiler, turning every 5 minutes, until charred and softened, 10 to 15 minutes. Transfer to a clean cutting board; when cool enough to handle, chop the peppers into bite-size pieces.\n"
},
{
"@type": "HowToStep",
"text": "Meanwhile, combine cumin, coriander, salt, turmeric, cinnamon and pepper in a small bowl. Grate 1/2 teaspoon zest from the lemon. Juice the lemon into a 1-cup measure and add enough water to make 1 cup. Pour into a small saucepan and add the lemon zest, 1 teaspoon of the spice mixture and 1 teaspoon olive oil. Bring to a boil. Stir in couscous, cover, remove from heat and let stand.\n"
},
{
"@type": "HowToStep",
"text": "Heat the remaining 1 tablespoon oil in a large skillet (preferably cast-iron) over medium heat until shimmering (but not smoking). Rub the remaining spice mixture on both sides of steak. Cook the steak 2 to 3 minutes per side for medium-rare. Let rest on the cutting board for 5 minutes. Stir olives and the peppers into the couscous. Thinly slice the steak and serve with the couscous and lemon wedges, if desired.\n"
}
],
"recipeCategory": [
"Healthy Recipes",
"Healthy Ingredient Recipes",
"Healthy Meat & Poultry Recipes",
"Healthy Beef Recipes",
"Healthy Steak Recipes",
"Healthy New York Strip Steak Recipes"
],
"recipeCuisine": [],
"author": [
{
"@type": "Person",
"name": "EatingWell Test Kitchen"
}
],
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": 4.538461538461538,
"ratingCount": 13,
"itemReviewed": "Moroccan Skirt Steak with Roasted Pepper Couscous",
"bestRating": "5",
"worstRating": "1"
},
"nutrition": {
"@type": "NutritionInformation",
"calories": "453.7 calories",
"carbohydrateContent": "36 g",
"cholesterolContent": "96.4 mg",
"fatContent": "18.4 g",
"fiberContent": "6.5 g",
"proteinContent": "36.4 g",
"saturatedFatContent": "5.1 g",
"servingSize": null,
"sodiumContent": "663.3 mg",
"sugarContent": null,
"transFatContent": null,
"unsaturatedFatContent": null
},
"review": [
{
"@type": "Review",
"datePublished": "2011-10-30T21:53:57Z",
"reviewBody": "Wow! This steak was fabulous. Full of flavor even my kids liked it. The spices for the steak rub get added to the cous cous. Along with the sweet roasted peppers it was so delicious.",
"reviewRating": {
"@type": "Rating",
"worstRating": "1",
"bestRating": "5",
"ratingValue": 5
},
"author": {
"@type": "Person",
"name": "shari_martinez@sbcglobal.net",
"image": null,
"sameAs": "https://www.allrecipes.com/cook/18308949/"
}
},
{
"@type": "Review",
"datePublished": "2011-10-30T02:40:11Z",
"reviewBody": "Not as well received as I had hoped The leftovers were good as a steak salad with honey-mustard seasoning although Kaja did not like the seasoned meat that way. I ate some couscous on my salad too. Leftover steak is unheard of at our house yet there it was. Offerred the kids a choice of unspiced steak (three takers) and Rice-a-Roni (four takers) Austin & I liked the steak Pros: Easy I liked it Cons: Nobody liked the couscous except me",
"reviewRating": {
"@type": "Rating",
"worstRating": "1",
"bestRating": "5",
"ratingValue": 3
},
"author": {
"@type": "Person",
"name": "Ellen",
"image": null,
"sameAs": "https://www.allrecipes.com/cook/19797391/"
}
},
{
"@type": "Review",
"datePublished": "2011-10-30T03:02:54Z",
"reviewBody": "tasty and easy weeknight meal Initially I was a little leery of using cinnamon to season the meat but it actually turned out very good. The seasoning had a tasty and light flavor. I used sirloin because the skirt steak at the store looked very fatty. The couscous (although I didn't add the olives because I'm not a huge fan) was also very good and I enjoyed the sweetness of the bell pepper. I used the lemon garnish to squeeze over the couscous and meat and think it made it. I would definitely make this again! Pros: Tasty and easy weeknight meal",
"reviewRating": {
"@type": "Rating",
"worstRating": "1",
"bestRating": "5",
"ratingValue": 4
},
"author": {
"@type": "Person",
"name": "Kat Y",
"image": null,
"sameAs": "https://www.allrecipes.com/cook/2343563/"
}
},
{
"@type": "Review",
"datePublished": "2011-10-30T17:25:23Z",
"reviewBody": "This was really good. It was definitely a change from what we're used to but in a good way. I had to use skillet steak because I couldn't find any skirt steak but it worked just fine. I also used the grill for the peppers and steak because my broiler is a bit questionable. Other than that I made it as stated and my husband and I really enjoyed it. A great out of the ordinary quick meal.",
"reviewRating": {
"@type": "Rating",
"worstRating": "1",
"bestRating": "5",
"ratingValue": 5
},
"author": {
"@type": "Person",
"name": "EatingWell User",
"image": null,
"sameAs": "https://www.allrecipes.com/cook/eatingwelluser/"
}
},
{
"@type": "Review",
"datePublished": "2011-10-30T03:41:53Z",
"reviewBody": "I love this recipe so much that I schedule it my meal planning as often as possible. The flavors with this cut of meat are just wonderful. I can't eat grains so I pair it with fennel. Perfect!",
"reviewRating": {
"@type": "Rating",
"worstRating": "1",
"bestRating": "5",
"ratingValue": 5
},
"author": {
"@type": "Person",
"name": "EatingWell User",
"image": null,
"sameAs": "https://www.allrecipes.com/cook/eatingwelluser/"
}
},
{
"@type": "Review",
"datePublished": "2013-02-20T17:33:48Z",
"reviewBody": "Great starting point! I like this one a lot but I would recommend the version of it on funnytummycafe.com. I've not been really adventurous with new flavors but this I will repeat! Pros: Wonderful flavors in the rub Cons: The couscous was TOO lemony",
"reviewRating": {
"@type": "Rating",
"worstRating": "1",
"bestRating": "5",
"ratingValue": 3
},
"author": {
"@type": "Person",
"name": "EatingWell User",
"image": null,
"sameAs": "https://www.allrecipes.com/cook/eatingwelluser/"
}
},
{
"@type": "Review",
"datePublished": "2011-10-30T15:06:11Z",
"reviewBody": "I made this with chicken instead of steak and it was great! My husband has not liked couscous in the past but he really liked this version. Will definitely make again!",
"reviewRating": {
"@type": "Rating",
"worstRating": "1",
"bestRating": "5",
"ratingValue": 5
},
"author": {
"@type": "Person",
"name": "EatingWell User",
"image": null,
"sameAs": "https://www.allrecipes.com/cook/eatingwelluser/"
}
},
{
"@type": "Review",
"datePublished": "2011-10-30T12:15:53Z",
"reviewBody": "WOW! Blew me away this was a great meal! Tons of flavor really quick and very filling! I served brown rice instead of couscous because that's what I had on hand. The husband never knew the difference! I can always tell when something is a real winner with him because he goes back for seconds (we're both on diets). I used one red and one green bell pepper and served a spring mix salad with tomato and feta on the side. Big bravo to the EatingWell kitchen! This will definitely be made again in my house!",
"reviewRating": {
"@type": "Rating",
"worstRating": "1",
"bestRating": "5",
"ratingValue": 5
},
"author": {
"@type": "Person",
"name": "EatingWell User",
"image": null,
"sameAs": "https://www.allrecipes.com/cook/eatingwelluser/"
}
},
{
"@type": "Review",
"datePublished": "2011-10-30T15:12:50Z",
"reviewBody": "Quick & easy to prepare with mild spiced flavor. The rub produces a great crust on the steak. I felt the lemon flavor dominated the cous cous though to be fair I did seem to have a particularly juicy lemon so that may be why. My husband and I both thought that the leftover steak would be superb sliced thinly in a sandwich with a mint/yogurt dressing.",
"reviewRating": {
"@type": "Rating",
"worstRating": "1",
"bestRating": "5",
"ratingValue": 5
},
"author": {
"@type": "Person",
"name": "EatingWell User",
"image": null,
"sameAs": "https://www.allrecipes.com/cook/eatingwelluser/"
}
}
],
"url": "http://www.eatingwell.com/recipe/249961/moroccan-skirt-steak-with-roasted-pepper-couscous/"
}

View file

@ -0,0 +1,9 @@
from mealie.services.scraper.cleaner import Cleaner
def test_clean_category():
assert Cleaner.category("my-category") == ["my-category"]
def test_clean_html():
assert Cleaner.html("<div>Hello World</div>") == "Hello World"

View file

@ -23,7 +23,7 @@ def test_zip_extraction(file_name: str, final_path: Path):
assert dir == final_path
cleanup()
assert dir.exists() == False
assert dir.exists() is False
@pytest.mark.parametrize(

View file

@ -62,22 +62,6 @@ def test_normalize_instructions(instructions):
]
# def test_html_no_recipe_data(): #! Unsure why it's failing, code didn't change?
# path = TEST_RAW_HTML.joinpath("carottes-rapps-with-rice-and-sunflower-seeds.html")
# url = "https://www.feedtheswimmers.com/blog/2019/6/5/carottes-rapps-with-rice-and-sunflower-seeds"
# recipe_data = extract_recipe_from_html(open(path).read(), url)
# assert len(recipe_data["name"]) > 10
# assert len(recipe_data["slug"]) > 10
# assert recipe_data["orgURL"] == url
# assert len(recipe_data["description"]) > 100
# assert url_validation_regex.match(recipe_data["image"])
# assert recipe_data["recipeIngredient"] == ["Could not detect ingredients"]
# assert recipe_data["recipeInstructions"] == [
# {"text": "Could not detect instructions"}
# ]
def test_html_with_recipe_data():
path = TEST_RAW_HTML.joinpath("healthy_pasta_bake_60759.html")
url = "https://www.bbc.co.uk/food/recipes/healthy_pasta_bake_60759"

View file

@ -0,0 +1,76 @@
from dataclasses import dataclass
@dataclass
class RecipeTestData:
url: str
expected_slug: str
def build_recipe_store():
return [
RecipeTestData(
url="https://www.bonappetit.com/recipe/spinach-thepla-and-vaghareli-dahi",
expected_slug="thepla-recipe-with-vaghareli-dahi",
),
RecipeTestData(
url="https://www.bonappetit.com/recipe/classic-coleslaw",
expected_slug="traditional-coleslaw-recipe",
),
]
def get_raw_recipe():
return {
"name": "Banana Bread",
"description": "From Angie's mom",
"image": "banana-bread.jpg",
"recipeYield": "",
"recipeIngredient": [
"4 bananas",
"1/2 cup butter",
"1/2 cup sugar",
"2 eggs",
"2 cups flour",
"1/2 tsp baking soda",
"1 tsp baking powder",
"pinch salt",
"1/4 cup nuts (we like pecans)",
],
"recipeInstructions": [
{
"@type": "Beat the eggs, then cream with the butter and sugar",
"text": "Beat the eggs, then cream with the butter and sugar",
},
{
"@type": "Mix in bananas, then flour, baking soda/powder, salt, and nuts",
"text": "Mix in bananas, then flour, baking soda/powder, salt, and nuts",
},
{
"@type": "Add to greased and floured pan",
"text": "Add to greased and floured pan",
},
{
"@type": "Bake until brown/cracked, toothpick comes out clean",
"text": "Bake until brown/cracked, toothpick comes out clean",
},
],
"totalTime": "None",
"prepTime": None,
"performTime": None,
"slug": "",
"categories": [],
"tags": ["breakfast", " baking"],
"dateAdded": "2021-01-12",
"notes": [],
"rating": 0,
"orgURL": None,
"extras": {},
}
def get_raw_no_image():
raw = get_raw_recipe()
raw["name"] = "Banana Bread No Image"
raw["image"] = ""
return raw

View file

@ -1,31 +0,0 @@
BASE = "/api"
ALL_RECIPES = BASE + "/recipes"
RECIPES_PREFIX = BASE + "/recipes"
RECIPES_ALL = RECIPES_PREFIX
RECIPES_CREATE = RECIPES_PREFIX + "/create"
RECIPES_CREATE_URL = RECIPES_PREFIX + "/create-url"
CATEGORIES_PREFIX = BASE + "/categories"
TAGS_PREFIX = BASE + "/tags"
MEALPLAN_PREFIX = BASE + "/meal-plans"
MEALPLAN_ALL = MEALPLAN_PREFIX + "/all"
MEALPLAN_CREATE = MEALPLAN_PREFIX + "/create"
MEALPLAN_THIS_WEEK = MEALPLAN_PREFIX + "/this-week"
MEALPLAN_TODAY = MEALPLAN_PREFIX + "/today"
SETTINGS_PREFIX = BASE + "/site-settings"
SETTINGS_UPDATE = SETTINGS_PREFIX
TEST_WEBHOOKS = SETTINGS_PREFIX + "/webhooks/test"
THEMES_PREFIX = BASE + "/themes"
THEMES_CREATE = THEMES_PREFIX + "/create"
BACKUPS_PREFIX = BASE + "/backups"
BACKUPS_AVAILABLE = BACKUPS_PREFIX + "/available"
BACKUPS_EXPORT = BACKUPS_PREFIX + "/export/database"
BACKUPS_UPLOAD = BACKUPS_PREFIX + "/upload"
MIGRATIONS_PREFIX = BASE + "/migrations"