mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-05-24 01:12:54 -04:00
Improve Test Coverage (#511)
* add recipe scaling notes * test theme rename * fix coverage call to use poetry * remove print * remove async * consolidate test case data * fix mealplan tests * remove redundant else Co-authored-by: hay-kot <hay-kot@pm.me>
This commit is contained in:
parent
c325a49fc2
commit
2dc9c8e843
@ -116,6 +116,7 @@
|
||||
- All images are now converted to .webp for better compression
|
||||
|
||||
### Behind the Scenes
|
||||
- The database layer has been added for future recipe scaling.
|
||||
- Black and Flake8 now run as CI/CD checks
|
||||
- New debian based docker image
|
||||
- Unified Sidebar Components
|
||||
|
4
makefile
4
makefile
@ -56,8 +56,8 @@ lint: ## 🧺 Check style with flake8
|
||||
|
||||
coverage: ## ☂️ Check code coverage quickly with the default Python
|
||||
poetry run pytest
|
||||
coverage report -m
|
||||
coverage html
|
||||
poetry run coverage report -m
|
||||
poetry run coverage html
|
||||
$(BROWSER) htmlcov/index.html
|
||||
|
||||
setup: ## 🏗 Setup Development Instance
|
||||
|
@ -34,7 +34,6 @@ def authenticate_user(session, email: str, password: str) -> UserInDB:
|
||||
if not user:
|
||||
return False
|
||||
|
||||
print(user)
|
||||
if not verify_password(password, user.password):
|
||||
return False
|
||||
return user
|
||||
|
@ -19,8 +19,7 @@ from mealie.schema.comments import CommentOut
|
||||
from mealie.schema.event_notifications import EventNotificationIn
|
||||
from mealie.schema.events import Event as EventSchema
|
||||
from mealie.schema.meal import MealPlanOut
|
||||
from mealie.schema.recipe import (Recipe, RecipeIngredientFood,
|
||||
RecipeIngredientUnit)
|
||||
from mealie.schema.recipe import Recipe, RecipeIngredientFood, RecipeIngredientUnit
|
||||
from mealie.schema.settings import CustomPageOut
|
||||
from mealie.schema.settings import SiteSettings as SiteSettingsSchema
|
||||
from mealie.schema.shopping_list import ShoppingListOut
|
||||
|
@ -85,7 +85,7 @@ def validate_long_live_token(session: Session, client_token: str, id: int) -> Us
|
||||
return token.user
|
||||
|
||||
|
||||
async def validate_file_token(token: Optional[str] = None) -> Path:
|
||||
def validate_file_token(token: Optional[str] = None) -> Path:
|
||||
credentials_exception = HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="could not validate file token",
|
||||
|
@ -38,14 +38,14 @@ def clean(recipe_data: dict, url=None) -> dict:
|
||||
def clean_string(text: str) -> str:
|
||||
if text == "" or text is None:
|
||||
return ""
|
||||
else:
|
||||
cleaned_text = html.unescape(text)
|
||||
cleaned_text = re.sub("<[^<]+?>", "", cleaned_text)
|
||||
cleaned_text = re.sub(" +", " ", cleaned_text)
|
||||
cleaned_text = re.sub("</p>", "\n", cleaned_text)
|
||||
cleaned_text = re.sub(r"\n\s*\n", "\n\n", cleaned_text)
|
||||
cleaned_text = cleaned_text.replace("\xa0", " ").replace("\t", " ").strip()
|
||||
return cleaned_text
|
||||
|
||||
cleaned_text = html.unescape(text)
|
||||
cleaned_text = re.sub("<[^<]+?>", "", cleaned_text)
|
||||
cleaned_text = re.sub(" +", " ", cleaned_text)
|
||||
cleaned_text = re.sub("</p>", "\n", cleaned_text)
|
||||
cleaned_text = re.sub(r"\n\s*\n", "\n\n", cleaned_text)
|
||||
cleaned_text = cleaned_text.replace("\xa0", " ").replace("\t", " ").strip()
|
||||
return cleaned_text
|
||||
|
||||
|
||||
def category(category: str):
|
||||
@ -82,6 +82,10 @@ def instructions(instructions) -> List[dict]:
|
||||
if not instructions:
|
||||
return []
|
||||
|
||||
# Dictionary (Keys: step number strings, Values: the instructions)
|
||||
if isinstance(instructions, dict):
|
||||
instructions = list(instructions.values())
|
||||
|
||||
if isinstance(instructions, list) and isinstance(instructions[0], list):
|
||||
instructions = instructions[0]
|
||||
|
||||
|
@ -11,7 +11,7 @@ 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
|
||||
from tests.utils.recipe_data import get_raw_no_image, get_raw_recipe, get_recipe_test_cases
|
||||
|
||||
main()
|
||||
|
||||
@ -71,4 +71,4 @@ def raw_recipe_no_image():
|
||||
|
||||
@fixture(scope="session")
|
||||
def recipe_store():
|
||||
return build_recipe_store()
|
||||
return get_recipe_test_cases()
|
||||
|
@ -4,16 +4,17 @@ 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
|
||||
from tests.utils.recipe_data import RecipeSiteTestCase, get_recipe_test_cases
|
||||
|
||||
recipe_test_data = build_recipe_store()
|
||||
recipe_test_data = get_recipe_test_cases()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("recipe_data", recipe_test_data)
|
||||
def test_create_by_url(api_client: TestClient, api_routes: AppRoutes, recipe_data: RecipeTestData, token):
|
||||
|
||||
def test_create_by_url(api_client: TestClient, api_routes: AppRoutes, recipe_data: RecipeSiteTestCase, 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
|
||||
|
||||
@ -35,7 +36,7 @@ def test_create_no_image(api_client: TestClient, api_routes: AppRoutes, token, r
|
||||
|
||||
|
||||
@pytest.mark.parametrize("recipe_data", recipe_test_data)
|
||||
def test_read_update(api_client: TestClient, api_routes: AppRoutes, recipe_data: RecipeTestData, token):
|
||||
def test_read_update(api_client: TestClient, api_routes: AppRoutes, recipe_data: RecipeSiteTestCase, 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
|
||||
@ -68,7 +69,7 @@ def test_read_update(api_client: TestClient, api_routes: AppRoutes, recipe_data:
|
||||
|
||||
|
||||
@pytest.mark.parametrize("recipe_data", recipe_test_data)
|
||||
def test_rename(api_client: TestClient, api_routes: AppRoutes, recipe_data: RecipeTestData, token):
|
||||
def test_rename(api_client: TestClient, api_routes: AppRoutes, recipe_data: RecipeSiteTestCase, 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
|
||||
@ -87,7 +88,7 @@ def test_rename(api_client: TestClient, api_routes: AppRoutes, recipe_data: Reci
|
||||
|
||||
|
||||
@pytest.mark.parametrize("recipe_data", recipe_test_data)
|
||||
def test_delete(api_client: TestClient, api_routes: AppRoutes, recipe_data: RecipeTestData, token):
|
||||
def test_delete(api_client: TestClient, api_routes: AppRoutes, recipe_data: RecipeSiteTestCase, 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
|
@ -1,104 +1,102 @@
|
||||
# import json
|
||||
import json
|
||||
|
||||
# import pytest
|
||||
# from fastapi.testclient import TestClient
|
||||
# from tests.app_routes import AppRoutes
|
||||
# from tests.utils.recipe_data import RecipeTestData
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from tests.app_routes import AppRoutes
|
||||
from tests.utils.recipe_data import RecipeSiteTestCase
|
||||
|
||||
|
||||
# def get_meal_plan_template(first=None, second=None):
|
||||
# return {
|
||||
# "group": "Home",
|
||||
# "startDate": "2021-01-18",
|
||||
# "endDate": "2021-01-19",
|
||||
# "meals": [
|
||||
# {
|
||||
# "slug": first,
|
||||
# "date": "2021-1-17",
|
||||
# },
|
||||
# {
|
||||
# "slug": second,
|
||||
# "date": "2021-1-18",
|
||||
# },
|
||||
# ],
|
||||
# }
|
||||
def get_meal_plan_template(first=None, second=None):
|
||||
return {
|
||||
"group": "Home",
|
||||
"startDate": "2021-01-18",
|
||||
"endDate": "2021-01-19",
|
||||
"planDays": [
|
||||
{
|
||||
"date": "2021-1-18",
|
||||
"meals": [{"slug": first, "name": "", "description": ""}],
|
||||
},
|
||||
{
|
||||
"date": "2021-1-19",
|
||||
"meals": [{"slug": second, "name": "", "description": ""}],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
# @pytest.fixture(scope="session")
|
||||
# def slug_1(api_client: TestClient, api_routes: AppRoutes, token, recipe_store: list[RecipeTestData]):
|
||||
# # Slug 1
|
||||
# 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)
|
||||
@pytest.fixture(scope="session")
|
||||
def slug_1(api_client: TestClient, api_routes: AppRoutes, token, recipe_store: list[RecipeSiteTestCase]):
|
||||
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
|
||||
yield slug_1
|
||||
|
||||
# api_client.delete(api_routes.recipes_recipe_slug(slug_1))
|
||||
api_client.delete(api_routes.recipes_recipe_slug(slug_1))
|
||||
|
||||
|
||||
# @pytest.fixture(scope="session")
|
||||
# def slug_2(api_client: TestClient, api_routes: AppRoutes, token, recipe_store: list[RecipeTestData]):
|
||||
# # Slug 2
|
||||
# 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)
|
||||
@pytest.fixture(scope="session")
|
||||
def slug_2(api_client: TestClient, api_routes: AppRoutes, token, recipe_store: list[RecipeSiteTestCase]):
|
||||
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
|
||||
yield slug_2
|
||||
|
||||
# api_client.delete(api_routes.recipes_recipe_slug(slug_2))
|
||||
api_client.delete(api_routes.recipes_recipe_slug(slug_2))
|
||||
|
||||
|
||||
# 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)
|
||||
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(api_routes.meal_plans_create, json=meal_plan, headers=token)
|
||||
# assert response.status_code == 201
|
||||
response = api_client.post(api_routes.meal_plans_create, json=meal_plan, headers=token)
|
||||
assert response.status_code == 201
|
||||
|
||||
|
||||
# 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)
|
||||
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
|
||||
assert response.status_code == 200
|
||||
|
||||
# meal_plan = get_meal_plan_template(slug_1, slug_2)
|
||||
meal_plan_template = get_meal_plan_template(slug_1, slug_2)
|
||||
|
||||
# new_meal_plan = json.loads(response.text)
|
||||
# meals = new_meal_plan[0]["meals"]
|
||||
created_meal_plan = json.loads(response.text)
|
||||
meals = created_meal_plan[0]["planDays"]
|
||||
|
||||
# assert meals[0]["slug"] == meal_plan["meals"][0]["slug"]
|
||||
# assert meals[1]["slug"] == meal_plan["meals"][1]["slug"]
|
||||
assert meals[0]["meals"][0]["slug"] == meal_plan_template["planDays"][0]["meals"][0]["slug"]
|
||||
assert meals[1]["meals"][0]["slug"] == meal_plan_template["planDays"][1]["meals"][0]["slug"]
|
||||
|
||||
|
||||
# def test_update_mealplan(api_client: TestClient, api_routes: AppRoutes, slug_1, slug_2, token):
|
||||
def test_update_mealplan(api_client: TestClient, api_routes: AppRoutes, slug_1, slug_2, token):
|
||||
|
||||
# response = api_client.get(api_routes.meal_plans_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]
|
||||
existing_mealplan = json.loads(response.text)
|
||||
existing_mealplan = existing_mealplan[0]
|
||||
|
||||
# # Swap
|
||||
# plan_uid = existing_mealplan.get("uid")
|
||||
# existing_mealplan["meals"][0]["slug"] = slug_2
|
||||
# existing_mealplan["meals"][1]["slug"] = slug_1
|
||||
# Swap
|
||||
plan_uid = existing_mealplan.get("uid")
|
||||
existing_mealplan["planDays"][0]["meals"][0]["slug"] = slug_2
|
||||
existing_mealplan["planDays"][1]["meals"][0]["slug"] = slug_1
|
||||
|
||||
# response = api_client.put(api_routes.meal_plans_plan_id(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
|
||||
assert response.status_code == 200
|
||||
|
||||
# response = api_client.get(api_routes.meal_plans_all, headers=token)
|
||||
# existing_mealplan = json.loads(response.text)
|
||||
# existing_mealplan = existing_mealplan[0]
|
||||
response = api_client.get(api_routes.meal_plans_all, headers=token)
|
||||
existing_mealplan = json.loads(response.text)
|
||||
existing_mealplan = existing_mealplan[0]
|
||||
|
||||
# assert existing_mealplan["meals"][0]["slug"] == slug_2
|
||||
# assert existing_mealplan["meals"][1]["slug"] == slug_1
|
||||
assert existing_mealplan["planDays"][0]["meals"][0]["slug"] == slug_2
|
||||
assert existing_mealplan["planDays"][1]["meals"][0]["slug"] == slug_1
|
||||
|
||||
|
||||
# def test_delete_mealplan(api_client: TestClient, api_routes: AppRoutes, token):
|
||||
# response = api_client.get(api_routes.meal_plans_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]
|
||||
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(api_routes.meal_plans_plan_id(plan_uid), headers=token)
|
||||
plan_uid = existing_mealplan.get("uid")
|
||||
response = api_client.delete(api_routes.meal_plans_plan_id(plan_uid), headers=token)
|
||||
|
||||
# assert response.status_code == 200
|
||||
assert response.status_code == 200
|
||||
|
@ -3,7 +3,6 @@ import json
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from mealie.schema.settings import SiteSettings
|
||||
from mealie.schema.theme import SiteTheme
|
||||
from tests.app_routes import AppRoutes
|
||||
|
||||
|
||||
@ -12,28 +11,6 @@ def default_settings():
|
||||
return SiteSettings().dict(by_alias=True)
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def default_theme():
|
||||
return SiteTheme(id=1).dict()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def new_theme():
|
||||
return {
|
||||
"id": 3,
|
||||
"name": "myTestTheme",
|
||||
"colors": {
|
||||
"primary": "#E58325",
|
||||
"accent": "#00457A",
|
||||
"secondary": "#973542",
|
||||
"success": "#43A047",
|
||||
"info": "#4990BA",
|
||||
"warning": "#FF4081",
|
||||
"error": "#EF5350",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_default_settings(api_client: TestClient, api_routes: AppRoutes, default_settings):
|
||||
response = api_client.get(api_routes.site_settings)
|
||||
|
||||
@ -52,59 +29,3 @@ def test_update_settings(api_client: TestClient, api_routes: AppRoutes, default_
|
||||
|
||||
response = api_client.get(api_routes.site_settings)
|
||||
assert json.loads(response.content) == default_settings
|
||||
|
||||
|
||||
def test_default_theme(api_client: TestClient, api_routes: AppRoutes, default_theme):
|
||||
response = api_client.get(api_routes.themes_id(1))
|
||||
assert response.status_code == 200
|
||||
assert json.loads(response.content) == default_theme
|
||||
|
||||
|
||||
def test_create_theme(api_client: TestClient, api_routes: AppRoutes, new_theme, token):
|
||||
|
||||
response = api_client.post(api_routes.themes_create, json=new_theme, headers=token)
|
||||
assert response.status_code == 201
|
||||
|
||||
response = api_client.get(api_routes.themes_id(new_theme.get("id")), headers=token)
|
||||
assert response.status_code == 200
|
||||
assert json.loads(response.content) == new_theme
|
||||
|
||||
|
||||
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
|
||||
response_dict = json.loads(response.content)
|
||||
assert default_theme in response_dict
|
||||
assert new_theme in response_dict
|
||||
|
||||
|
||||
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(api_routes.themes_id(theme.get("id")))
|
||||
assert response.status_code == 200
|
||||
assert json.loads(response.content) == theme
|
||||
|
||||
|
||||
def test_update_theme(api_client: TestClient, api_routes: AppRoutes, token, default_theme, new_theme):
|
||||
theme_colors = {
|
||||
"primary": "#E12345",
|
||||
"accent": "#012345",
|
||||
"secondary": "#973542",
|
||||
"success": "#5AB1BB",
|
||||
"info": "#4990BA",
|
||||
"warning": "#FF4081",
|
||||
"error": "#EF4432",
|
||||
}
|
||||
|
||||
new_theme["colors"] = theme_colors
|
||||
response = api_client.put(api_routes.themes_id(new_theme.get("id")), json=new_theme, headers=token)
|
||||
assert response.status_code == 200
|
||||
response = api_client.get(api_routes.themes_id(new_theme.get("id")))
|
||||
assert json.loads(response.content) == new_theme
|
||||
|
||||
|
||||
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(api_routes.themes_id(theme.get("id")), headers=token)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
85
tests/integration_tests/test_theme_routes.py
Normal file
85
tests/integration_tests/test_theme_routes.py
Normal file
@ -0,0 +1,85 @@
|
||||
import json
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from mealie.schema.theme import SiteTheme
|
||||
from tests.app_routes import AppRoutes
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def default_theme():
|
||||
return SiteTheme(id=1).dict()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def new_theme():
|
||||
return {
|
||||
"id": 3,
|
||||
"name": "myTestTheme",
|
||||
"colors": {
|
||||
"primary": "#E58325",
|
||||
"accent": "#00457A",
|
||||
"secondary": "#973542",
|
||||
"success": "#43A047",
|
||||
"info": "#4990BA",
|
||||
"warning": "#FF4081",
|
||||
"error": "#EF5350",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_default_theme(api_client: TestClient, api_routes: AppRoutes, default_theme):
|
||||
response = api_client.get(api_routes.themes_id(1))
|
||||
assert response.status_code == 200
|
||||
assert json.loads(response.content) == default_theme
|
||||
|
||||
|
||||
def test_create_theme(api_client: TestClient, api_routes: AppRoutes, new_theme, token):
|
||||
|
||||
response = api_client.post(api_routes.themes_create, json=new_theme, headers=token)
|
||||
assert response.status_code == 201
|
||||
|
||||
response = api_client.get(api_routes.themes_id(new_theme.get("id")), headers=token)
|
||||
assert response.status_code == 200
|
||||
assert json.loads(response.content) == new_theme
|
||||
|
||||
|
||||
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
|
||||
response_dict = json.loads(response.content)
|
||||
assert default_theme in response_dict
|
||||
assert new_theme in response_dict
|
||||
|
||||
|
||||
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(api_routes.themes_id(theme.get("id")))
|
||||
assert response.status_code == 200
|
||||
assert json.loads(response.content) == theme
|
||||
|
||||
|
||||
def test_update_theme(api_client: TestClient, api_routes: AppRoutes, token, new_theme):
|
||||
theme_colors = {
|
||||
"primary": "#E12345",
|
||||
"accent": "#012345",
|
||||
"secondary": "#973542",
|
||||
"success": "#5AB1BB",
|
||||
"info": "#4990BA",
|
||||
"warning": "#FF4081",
|
||||
"error": "#EF4432",
|
||||
}
|
||||
|
||||
new_theme["colors"] = theme_colors
|
||||
new_theme["name"] = "New Theme Name"
|
||||
response = api_client.put(api_routes.themes_id(new_theme.get("id")), json=new_theme, headers=token)
|
||||
assert response.status_code == 200
|
||||
response = api_client.get(api_routes.themes_id(new_theme.get("id")))
|
||||
assert json.loads(response.content) == new_theme
|
||||
|
||||
|
||||
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(api_routes.themes_id(theme.get("id")), headers=token)
|
||||
|
||||
assert response.status_code == 200
|
@ -34,6 +34,13 @@ def new_user():
|
||||
)
|
||||
|
||||
|
||||
def test_failed_login(api_client: TestClient, api_routes: AppRoutes):
|
||||
form_data = {"username": "changeme@email.com", "password": "WRONG_PASSWORD"}
|
||||
response = api_client.post(api_routes.auth_token, form_data)
|
||||
|
||||
assert response.status_code == 401
|
||||
|
||||
|
||||
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)
|
||||
|
@ -1,57 +1,17 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
import pytest
|
||||
from mealie.services.scraper import scraper
|
||||
from tests.utils.recipe_data import RecipeSiteTestCase, get_recipe_test_cases
|
||||
|
||||
test_cases = get_recipe_test_cases()
|
||||
|
||||
"""
|
||||
These tests are skipped by default and only really used when troubleshooting the parser
|
||||
directly. If you are working on improve the parser you can add test cases to the `get_recipe_test_cases` function
|
||||
and then use this test case by removing the `@pytest.mark.skip` and than testing your results.
|
||||
"""
|
||||
|
||||
|
||||
@dataclass
|
||||
class RecipeSiteTestCase:
|
||||
url: str
|
||||
expected_slug: str
|
||||
num_ingredients: int
|
||||
num_steps: int
|
||||
|
||||
|
||||
test_cases = [
|
||||
RecipeSiteTestCase(
|
||||
url="https://www.seriouseats.com/taiwanese-three-cup-chicken-san-bei-gi-recipe",
|
||||
expected_slug="taiwanese-three-cup-chicken-san-bei-ji-recipe",
|
||||
num_ingredients=10,
|
||||
num_steps=3,
|
||||
),
|
||||
RecipeSiteTestCase(
|
||||
url="https://www.rezeptwelt.de/backen-herzhaft-rezepte/schinken-kaese-waffeln-ohne-viel-schnickschnack/4j0bkiig-94d4d-106529-cfcd2-is97x2ml",
|
||||
expected_slug="schinken-kase-waffeln-ohne-viel-schnickschnack",
|
||||
num_ingredients=7,
|
||||
num_steps=1, # Malformed JSON Data, can't parse steps just get one string
|
||||
),
|
||||
RecipeSiteTestCase(
|
||||
url="https://cookpad.com/us/recipes/5544853-sous-vide-smoked-beef-ribs",
|
||||
expected_slug="sous-vide-smoked-beef-ribs",
|
||||
num_ingredients=7,
|
||||
num_steps=12,
|
||||
),
|
||||
RecipeSiteTestCase(
|
||||
url="https://www.greatbritishchefs.com/recipes/jam-roly-poly-recipe",
|
||||
expected_slug="jam-roly-poly-with-custard",
|
||||
num_ingredients=13,
|
||||
num_steps=9,
|
||||
),
|
||||
RecipeSiteTestCase(
|
||||
url="https://recipes.anovaculinary.com/recipe/sous-vide-shrimp",
|
||||
expected_slug="sous-vide-shrimp",
|
||||
num_ingredients=5,
|
||||
num_steps=0,
|
||||
),
|
||||
RecipeSiteTestCase(
|
||||
url="https://www.bonappetit.com/recipe/detroit-style-pepperoni-pizza",
|
||||
expected_slug="detroit-style-pepperoni-pizza",
|
||||
num_ingredients=8,
|
||||
num_steps=5,
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.skip
|
||||
@pytest.mark.parametrize("recipe_test_data", test_cases)
|
||||
def test_recipe_parser(recipe_test_data: RecipeSiteTestCase):
|
||||
recipe = scraper.create_from_url(recipe_test_data.url)
|
||||
|
11
tests/unit_tests/test_security.py
Normal file
11
tests/unit_tests/test_security.py
Normal file
@ -0,0 +1,11 @@
|
||||
from pathlib import Path
|
||||
|
||||
from mealie.core import security
|
||||
from mealie.routes.deps import validate_file_token
|
||||
|
||||
|
||||
def test_create_file_token():
|
||||
file_path = Path(__file__).parent
|
||||
file_token = security.create_file_token(file_path)
|
||||
|
||||
assert file_path == validate_file_token(file_token)
|
3
tests/utils/helpers.py
Normal file
3
tests/utils/helpers.py
Normal file
@ -0,0 +1,3 @@
|
||||
class MatchAny:
|
||||
def __eq__(self, _: object) -> bool:
|
||||
return True
|
@ -2,20 +2,50 @@ from dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass
|
||||
class RecipeTestData:
|
||||
class RecipeSiteTestCase:
|
||||
url: str
|
||||
expected_slug: str
|
||||
num_ingredients: int
|
||||
num_steps: int
|
||||
|
||||
|
||||
def build_recipe_store():
|
||||
def get_recipe_test_cases():
|
||||
return [
|
||||
RecipeTestData(
|
||||
url="https://www.bonappetit.com/recipe/spinach-thepla-and-vaghareli-dahi",
|
||||
expected_slug="thepla-recipe-with-vaghareli-dahi",
|
||||
RecipeSiteTestCase(
|
||||
url="https://www.seriouseats.com/taiwanese-three-cup-chicken-san-bei-gi-recipe",
|
||||
expected_slug="taiwanese-three-cup-chicken-san-bei-ji-recipe",
|
||||
num_ingredients=10,
|
||||
num_steps=3,
|
||||
),
|
||||
RecipeTestData(
|
||||
url="https://www.bonappetit.com/recipe/classic-coleslaw",
|
||||
expected_slug="traditional-coleslaw-recipe",
|
||||
RecipeSiteTestCase(
|
||||
url="https://www.rezeptwelt.de/backen-herzhaft-rezepte/schinken-kaese-waffeln-ohne-viel-schnickschnack/4j0bkiig-94d4d-106529-cfcd2-is97x2ml",
|
||||
expected_slug="schinken-kase-waffeln-ohne-viel-schnickschnack",
|
||||
num_ingredients=7,
|
||||
num_steps=1, # Malformed JSON Data, can't parse steps just get one string
|
||||
),
|
||||
RecipeSiteTestCase(
|
||||
url="https://cookpad.com/us/recipes/5544853-sous-vide-smoked-beef-ribs",
|
||||
expected_slug="sous-vide-smoked-beef-ribs",
|
||||
num_ingredients=7,
|
||||
num_steps=12,
|
||||
),
|
||||
RecipeSiteTestCase(
|
||||
url="https://www.greatbritishchefs.com/recipes/jam-roly-poly-recipe",
|
||||
expected_slug="jam-roly-poly-with-custard",
|
||||
num_ingredients=13,
|
||||
num_steps=9,
|
||||
),
|
||||
RecipeSiteTestCase(
|
||||
url="https://recipes.anovaculinary.com/recipe/sous-vide-shrimp",
|
||||
expected_slug="sous-vide-shrimp",
|
||||
num_ingredients=5,
|
||||
num_steps=0,
|
||||
),
|
||||
RecipeSiteTestCase(
|
||||
url="https://www.bonappetit.com/recipe/detroit-style-pepperoni-pizza",
|
||||
expected_slug="detroit-style-pepperoni-pizza",
|
||||
num_ingredients=8,
|
||||
num_steps=5,
|
||||
),
|
||||
]
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user