2024-05-31 09:58:04 +00:00

156 lines
5.3 KiB
Python

import os
from dataclasses import dataclass
from pathlib import Path
from tempfile import TemporaryDirectory
from zipfile import ZipFile
import pytest
from fastapi.testclient import TestClient
from mealie.schema.group.group_migration import SupportedMigrations
from mealie.schema.reports.reports import ReportEntryOut
from tests import data as test_data
from tests.utils import api_routes
from tests.utils.assertion_helpers import assert_derserialize
from tests.utils.fixture_schemas import TestUser
@dataclass
class MigrationTestData:
typ: SupportedMigrations
archive: Path
test_cases = [
MigrationTestData(typ=SupportedMigrations.nextcloud, archive=test_data.migrations_nextcloud),
MigrationTestData(typ=SupportedMigrations.paprika, archive=test_data.migrations_paprika),
MigrationTestData(typ=SupportedMigrations.chowdown, archive=test_data.migrations_chowdown),
MigrationTestData(typ=SupportedMigrations.copymethat, archive=test_data.migrations_copymethat),
MigrationTestData(typ=SupportedMigrations.mealie_alpha, archive=test_data.migrations_mealie),
MigrationTestData(typ=SupportedMigrations.tandoor, archive=test_data.migrations_tandoor),
MigrationTestData(typ=SupportedMigrations.plantoeat, archive=test_data.migrations_plantoeat),
MigrationTestData(typ=SupportedMigrations.myrecipebox, archive=test_data.migrations_myrecipebox),
MigrationTestData(typ=SupportedMigrations.recipekeeper, archive=test_data.migrations_recipekeeper),
]
test_ids = [
"nextcloud_archive",
"paprika_archive",
"chowdown_archive",
"copymethat_archive",
"mealie_alpha_archive",
"tandoor_archive",
"plantoeat_archive",
"myrecipebox_csv",
"recipekeeper_archive",
]
@pytest.mark.parametrize("mig", test_cases, ids=test_ids)
def test_recipe_migration(api_client: TestClient, unique_user: TestUser, mig: MigrationTestData) -> None:
payload = {
"migration_type": mig.typ.value,
}
file_payload = {
"archive": mig.archive.read_bytes(),
}
response = api_client.post(
api_routes.groups_migrations,
data=payload,
files=file_payload,
headers=unique_user.token,
)
assert response.status_code == 200
report_id = response.json()["id"]
# Validate Results
response = api_client.get(api_routes.groups_reports_item_id(report_id), headers=unique_user.token)
assert response.status_code == 200
response_json = response.json()
assert response_json["entries"]
for item in response_json["entries"]:
assert item["success"]
# Validate Create Event
params = {"orderBy": "created_at", "orderDirection": "desc"}
response = api_client.get(api_routes.recipes, params=params, headers=unique_user.token)
query_data = assert_derserialize(response)
assert len(query_data["items"])
recipe_id = query_data["items"][0]["id"]
params = {"queryFilter": f"recipe_id={recipe_id}"}
response = api_client.get(api_routes.recipes_timeline_events, params=params, headers=unique_user.token)
query_data = assert_derserialize(response)
events = query_data["items"]
assert len(events)
def test_bad_mealie_alpha_data_is_ignored(api_client: TestClient, unique_user: TestUser):
with TemporaryDirectory() as tmpdir:
with ZipFile(test_data.migrations_mealie) as zf:
zf.extractall(tmpdir)
invalid_recipe_dir = os.path.join(tmpdir, "mealie_2021-Dec-08", "recipes", "invalid-recipe")
os.makedirs(invalid_recipe_dir, exist_ok=True)
invalid_json_path = os.path.join(invalid_recipe_dir, "invalid-recipe.json")
try:
with open(invalid_json_path, "w"):
pass # write nothing to the file, which is invalid JSON
except Exception:
raise Exception(os.listdir(tmpdir))
modified_test_data = os.path.join(tmpdir, "modified-test-data.zip")
with ZipFile(modified_test_data, "w") as zf:
for root, _, files in os.walk(tmpdir):
for file in files:
file_path = os.path.join(root, file)
zf.write(file_path, arcname=os.path.relpath(file_path, tmpdir))
payload = {
"migration_type": SupportedMigrations.mealie_alpha.value,
}
file_payload = {
"archive": Path(modified_test_data).read_bytes(),
}
response = api_client.post(
api_routes.groups_migrations,
data=payload,
files=file_payload,
headers=unique_user.token,
)
assert response.status_code == 200
report_id = response.json()["id"]
# Validate Results
response = api_client.get(api_routes.groups_reports_item_id(report_id), headers=unique_user.token)
assert response.status_code == 200
response_json = response.json()
assert response_json["entries"]
failed_item = None
failed_item_count = 0
for item in response_json["entries"]:
if item["success"]:
continue
failed_item = item
failed_item_count += 1
assert failed_item
assert failed_item_count == 1
report_entry = ReportEntryOut.model_validate(failed_item)
assert report_entry.message == "Failed to import invalid-recipe.json"
assert report_entry.exception == "JSONDecodeError: Expecting value: line 1 column 1 (char 0)"