2022-01-13 13:06:52 -09:00
|
|
|
import random
|
2024-09-22 09:59:20 -05:00
|
|
|
from collections.abc import Generator
|
2022-01-13 13:06:52 -09:00
|
|
|
from dataclasses import dataclass
|
2021-12-04 14:18:46 -09:00
|
|
|
from uuid import UUID
|
|
|
|
|
2022-01-13 13:06:52 -09:00
|
|
|
import pytest
|
2021-09-05 22:05:29 -08:00
|
|
|
from fastapi.testclient import TestClient
|
2022-02-20 14:17:51 -09:00
|
|
|
from pydantic import UUID4
|
2021-09-05 22:05:29 -08:00
|
|
|
|
2022-01-13 13:06:52 -09:00
|
|
|
from mealie.schema.cookbook.cookbook import ReadCookBook, SaveCookBook
|
2022-02-20 14:17:51 -09:00
|
|
|
from tests import utils
|
2022-10-18 14:49:41 -08:00
|
|
|
from tests.utils import api_routes
|
2022-01-13 13:06:52 -09:00
|
|
|
from tests.utils.factories import random_string
|
2021-12-04 14:18:46 -09:00
|
|
|
from tests.utils.fixture_schemas import TestUser
|
|
|
|
|
2021-09-05 22:05:29 -08:00
|
|
|
|
2024-08-22 10:14:32 -05:00
|
|
|
def get_page_data(group_id: UUID | str, household_id: UUID4 | str):
|
2022-01-13 13:06:52 -09:00
|
|
|
name_and_slug = random_string(10)
|
2021-12-04 14:18:46 -09:00
|
|
|
return {
|
2022-01-13 13:06:52 -09:00
|
|
|
"name": name_and_slug,
|
|
|
|
"slug": name_and_slug,
|
2021-12-04 14:18:46 -09:00
|
|
|
"description": "",
|
|
|
|
"position": 0,
|
2024-10-17 10:35:39 -05:00
|
|
|
"query_filter_string": "",
|
2022-01-13 13:06:52 -09:00
|
|
|
"group_id": str(group_id),
|
2024-08-22 10:14:32 -05:00
|
|
|
"household_id": str(household_id),
|
2021-12-04 14:18:46 -09:00
|
|
|
}
|
2021-09-05 22:05:29 -08:00
|
|
|
|
|
|
|
|
2022-01-13 13:06:52 -09:00
|
|
|
@dataclass
|
|
|
|
class TestCookbook:
|
2022-02-20 14:17:51 -09:00
|
|
|
id: UUID4
|
2022-01-13 13:06:52 -09:00
|
|
|
slug: str
|
|
|
|
name: str
|
|
|
|
data: dict
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope="function")
|
2024-09-22 09:59:20 -05:00
|
|
|
def cookbooks(unique_user: TestUser) -> Generator[list[TestCookbook]]:
|
2024-08-22 10:14:32 -05:00
|
|
|
database = unique_user.repos
|
|
|
|
|
2022-01-13 13:06:52 -09:00
|
|
|
data: list[ReadCookBook] = []
|
|
|
|
yield_data: list[TestCookbook] = []
|
|
|
|
for _ in range(3):
|
2024-08-22 10:14:32 -05:00
|
|
|
cb = database.cookbooks.create(SaveCookBook(**get_page_data(unique_user.group_id, unique_user.household_id)))
|
2024-09-22 09:59:20 -05:00
|
|
|
assert cb.slug
|
2022-01-13 13:06:52 -09:00
|
|
|
data.append(cb)
|
2024-02-11 10:47:37 -06:00
|
|
|
yield_data.append(TestCookbook(id=cb.id, slug=cb.slug, name=cb.name, data=cb.model_dump()))
|
2022-01-13 13:06:52 -09:00
|
|
|
|
|
|
|
yield yield_data
|
|
|
|
|
2024-09-22 09:59:20 -05:00
|
|
|
for cb in data:
|
2022-01-13 13:06:52 -09:00
|
|
|
try:
|
|
|
|
database.cookbooks.delete(cb.id)
|
|
|
|
except Exception:
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
2021-12-04 14:18:46 -09:00
|
|
|
def test_create_cookbook(api_client: TestClient, unique_user: TestUser):
|
2024-08-22 10:14:32 -05:00
|
|
|
page_data = get_page_data(unique_user.group_id, unique_user.household_id)
|
|
|
|
response = api_client.post(api_routes.households_cookbooks, json=page_data, headers=unique_user.token)
|
2021-09-12 11:05:09 -08:00
|
|
|
assert response.status_code == 201
|
2021-09-05 22:05:29 -08:00
|
|
|
|
|
|
|
|
2024-10-15 12:54:58 -05:00
|
|
|
@pytest.mark.parametrize("name_input", ["", " ", "@"])
|
|
|
|
def test_create_cookbook_bad_name(api_client: TestClient, unique_user: TestUser, name_input: str):
|
|
|
|
data = {
|
|
|
|
"name": name_input,
|
|
|
|
"slug": name_input,
|
|
|
|
"description": "",
|
|
|
|
"position": 0,
|
|
|
|
"categories": [],
|
|
|
|
"group_id": str(unique_user.group_id),
|
|
|
|
"household_id": str(unique_user.household_id),
|
|
|
|
}
|
|
|
|
|
|
|
|
response = api_client.post(api_routes.households_cookbooks, json=data, headers=unique_user.token)
|
|
|
|
assert response.status_code == 422
|
|
|
|
|
|
|
|
|
2022-01-13 13:06:52 -09:00
|
|
|
def test_read_cookbook(api_client: TestClient, unique_user: TestUser, cookbooks: list[TestCookbook]):
|
|
|
|
sample = random.choice(cookbooks)
|
2024-08-22 10:14:32 -05:00
|
|
|
response = api_client.get(api_routes.households_cookbooks_item_id(sample.id), headers=unique_user.token)
|
2022-01-13 13:06:52 -09:00
|
|
|
assert response.status_code == 200
|
2022-04-01 09:50:31 -08:00
|
|
|
|
|
|
|
page_data = response.json()
|
|
|
|
|
|
|
|
assert page_data["id"] == str(sample.id)
|
|
|
|
assert page_data["slug"] == sample.slug
|
|
|
|
assert page_data["name"] == sample.name
|
|
|
|
assert page_data["groupId"] == str(unique_user.group_id)
|
2021-09-05 22:05:29 -08:00
|
|
|
|
|
|
|
|
2022-02-20 14:17:51 -09:00
|
|
|
def test_update_cookbook(api_client: TestClient, unique_user: TestUser, cookbooks: list[TestCookbook]):
|
|
|
|
cookbook = random.choice(cookbooks)
|
|
|
|
|
2024-08-22 10:14:32 -05:00
|
|
|
update_data = get_page_data(unique_user.group_id, unique_user.household_id)
|
2021-09-05 22:05:29 -08:00
|
|
|
|
2022-02-20 14:17:51 -09:00
|
|
|
update_data["name"] = random_string(10)
|
2021-12-04 14:18:46 -09:00
|
|
|
|
2022-10-18 14:49:41 -08:00
|
|
|
response = api_client.put(
|
2024-08-22 10:14:32 -05:00
|
|
|
api_routes.households_cookbooks_item_id(cookbook.id), json=update_data, headers=unique_user.token
|
2022-10-18 14:49:41 -08:00
|
|
|
)
|
2022-01-13 13:06:52 -09:00
|
|
|
assert response.status_code == 200
|
|
|
|
|
2024-08-22 10:14:32 -05:00
|
|
|
response = api_client.get(api_routes.households_cookbooks_item_id(cookbook.id), headers=unique_user.token)
|
2022-02-20 14:17:51 -09:00
|
|
|
assert response.status_code == 200
|
|
|
|
|
|
|
|
page_data = response.json()
|
|
|
|
assert page_data["name"] == update_data["name"]
|
|
|
|
assert page_data["slug"] == update_data["name"]
|
|
|
|
|
2022-01-13 13:06:52 -09:00
|
|
|
|
|
|
|
def test_update_cookbooks_many(api_client: TestClient, unique_user: TestUser, cookbooks: list[TestCookbook]):
|
|
|
|
pages = [x.data for x in cookbooks]
|
2021-09-05 22:05:29 -08:00
|
|
|
|
2022-01-13 13:06:52 -09:00
|
|
|
reverse_order = sorted(pages, key=lambda x: x["position"], reverse=True)
|
|
|
|
for x, page in enumerate(reverse_order):
|
|
|
|
page["position"] = x
|
|
|
|
page["group_id"] = str(unique_user.group_id)
|
|
|
|
|
2024-08-22 10:14:32 -05:00
|
|
|
response = api_client.put(
|
|
|
|
api_routes.households_cookbooks, json=utils.jsonify(reverse_order), headers=unique_user.token
|
|
|
|
)
|
2021-09-05 22:05:29 -08:00
|
|
|
assert response.status_code == 200
|
|
|
|
|
2024-08-22 10:14:32 -05:00
|
|
|
response = api_client.get(api_routes.households_cookbooks, headers=unique_user.token)
|
2022-01-13 13:06:52 -09:00
|
|
|
assert response.status_code == 200
|
|
|
|
|
|
|
|
known_ids = [x.id for x in cookbooks]
|
|
|
|
|
2022-06-25 14:39:38 -05:00
|
|
|
server_ids = [x["id"] for x in response.json()["items"]]
|
2022-01-13 13:06:52 -09:00
|
|
|
|
|
|
|
for know in known_ids: # Hacky check, because other tests don't cleanup after themselves :(
|
2022-02-20 14:17:51 -09:00
|
|
|
assert str(know) in server_ids
|
2022-01-13 13:06:52 -09:00
|
|
|
|
2021-09-05 22:05:29 -08:00
|
|
|
|
2022-01-13 13:06:52 -09:00
|
|
|
def test_delete_cookbook(api_client: TestClient, unique_user: TestUser, cookbooks: list[TestCookbook]):
|
|
|
|
sample = random.choice(cookbooks)
|
2024-08-22 10:14:32 -05:00
|
|
|
response = api_client.delete(api_routes.households_cookbooks_item_id(sample.id), headers=unique_user.token)
|
2021-09-05 22:05:29 -08:00
|
|
|
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
2024-08-22 10:14:32 -05:00
|
|
|
response = api_client.get(api_routes.households_cookbooks_item_id(sample.slug), headers=unique_user.token)
|
2021-09-05 22:05:29 -08:00
|
|
|
assert response.status_code == 404
|
2024-10-17 10:35:39 -05:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
"qf_string, expected_code",
|
|
|
|
[
|
|
|
|
('tags.name CONTAINS ALL ["tag1","tag2"]', 200),
|
|
|
|
('badfield = "badvalue"', 422),
|
|
|
|
('recipe_category.id IN ["1"]', 422),
|
|
|
|
('created_at >= "not-a-date"', 422),
|
|
|
|
],
|
|
|
|
ids=[
|
|
|
|
"valid qf",
|
|
|
|
"invalid field",
|
|
|
|
"invalid UUID",
|
|
|
|
"invalid date",
|
|
|
|
],
|
|
|
|
)
|
|
|
|
def test_cookbook_validate_query_filter_string(
|
|
|
|
api_client: TestClient, unique_user: TestUser, qf_string: str, expected_code: int
|
|
|
|
):
|
|
|
|
# Create
|
|
|
|
cb_data = {"name": random_string(10), "slug": random_string(10), "query_filter_string": qf_string}
|
|
|
|
response = api_client.post(api_routes.households_cookbooks, json=cb_data, headers=unique_user.token)
|
|
|
|
assert response.status_code == expected_code if expected_code != 200 else 201
|
|
|
|
|
|
|
|
# Update
|
|
|
|
cb_data = {"name": random_string(10), "slug": random_string(10), "query_filter_string": ""}
|
|
|
|
response = api_client.post(api_routes.households_cookbooks, json=cb_data, headers=unique_user.token)
|
|
|
|
assert response.status_code == 201
|
|
|
|
cb_data = response.json()
|
|
|
|
|
|
|
|
cb_data["queryFilterString"] = qf_string
|
|
|
|
response = api_client.put(
|
|
|
|
api_routes.households_cookbooks_item_id(cb_data["id"]), json=cb_data, headers=unique_user.token
|
|
|
|
)
|
|
|
|
assert response.status_code == expected_code if expected_code != 201 else 200
|
|
|
|
|
|
|
|
# Out; should skip validation, so this should never error out
|
|
|
|
ReadCookBook(**cb_data)
|