mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-08-05 21:45:25 +02:00
feat: random sort option for front page (#2363)
* Add hook for random sorting * Add random sorting to front page * Add multiple tests for random sorting. * Be extra sure that all recipes are returned. * Too stable random. seed doesn't reach backend. * add timestamp to useRecipeSearch * Update randomization tests for timestamp seeding * ruff cleanup * pass timestamp separately in getAll * remove debugging log items * remove timestamp from address bar * remove defaults from backend timestamps * timestamp should be optional * fix edge case: query without timestamp * similar edge case: no timestamp in pagination * ruff :/ * better edge case handling * stabilize random search test w/more recipes * better pagination seeding * update pagination seed test * remove redundant random/seed check * Test for api routes to random sorting. * please the typing gods * hack to make query parameters throw correct exc * ruff * fix validator message typo * black reformatting --------- Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>
This commit is contained in:
parent
7e0d29afc7
commit
e1d3a247c7
10 changed files with 202 additions and 7 deletions
|
@ -424,3 +424,28 @@ def test_get_recipe_by_slug_or_id(api_client: TestClient, unique_user: utils.Tes
|
|||
recipe_data = response.json()
|
||||
assert recipe_data["slug"] == slug
|
||||
assert recipe_data["id"] == recipe_id
|
||||
|
||||
|
||||
def test_get_random_order(api_client: TestClient, unique_user: utils.TestUser):
|
||||
# Create more recipes for stable random ordering
|
||||
slugs = [random_string(10) for _ in range(7)]
|
||||
for slug in slugs:
|
||||
response = api_client.post(api_routes.recipes, json={"name": slug}, headers=unique_user.token)
|
||||
assert response.status_code == 201
|
||||
assert json.loads(response.text) == slug
|
||||
|
||||
goodparams: dict[str, int | str] = {"page": 1, "perPage": -1, "orderBy": "random", "paginationSeed": "abcdefg"}
|
||||
response = api_client.get(api_routes.recipes, params=goodparams, headers=unique_user.token)
|
||||
assert response.status_code == 200
|
||||
|
||||
seed1_params: dict[str, int | str] = {"page": 1, "perPage": -1, "orderBy": "random", "paginationSeed": "abcdefg"}
|
||||
seed2_params: dict[str, int | str] = {"page": 1, "perPage": -1, "orderBy": "random", "paginationSeed": "gfedcba"}
|
||||
data1 = api_client.get(api_routes.recipes, params=seed1_params, headers=unique_user.token).json()
|
||||
data2 = api_client.get(api_routes.recipes, params=seed2_params, headers=unique_user.token).json()
|
||||
data1_new = api_client.get(api_routes.recipes, params=seed1_params, headers=unique_user.token).json()
|
||||
assert data1["items"][0]["slug"] != data2["items"][0]["slug"] # new seed -> new order
|
||||
assert data1["items"][0]["slug"] == data1_new["items"][0]["slug"] # same seed -> same order
|
||||
|
||||
badparams: dict[str, int | str] = {"page": 1, "perPage": -1, "orderBy": "random"}
|
||||
response = api_client.get(api_routes.recipes, params=badparams, headers=unique_user.token)
|
||||
assert response.status_code == 422
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from datetime import datetime
|
||||
from typing import cast
|
||||
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
|
@ -200,6 +201,20 @@ def test_recipe_repo_pagination_by_categories(database: AllRepositories, unique_
|
|||
for category in created_categories:
|
||||
assert category.id in category_ids
|
||||
|
||||
# Test random ordering with category filter
|
||||
pagination_query = PaginationQuery(
|
||||
page=1,
|
||||
per_page=-1,
|
||||
order_by="random",
|
||||
pagination_seed=str(datetime.now()),
|
||||
order_direction=OrderDirection.asc,
|
||||
)
|
||||
random_ordered = []
|
||||
for i in range(5):
|
||||
pagination_query.pagination_seed = str(datetime.now())
|
||||
random_ordered.append(database.recipes.page_all(pagination_query, categories=[category_slug]).items)
|
||||
assert not all(i == random_ordered[0] for i in random_ordered)
|
||||
|
||||
|
||||
def test_recipe_repo_pagination_by_tags(database: AllRepositories, unique_user: TestUser):
|
||||
slug1, slug2 = (random_string(10) for _ in range(2))
|
||||
|
@ -279,6 +294,21 @@ def test_recipe_repo_pagination_by_tags(database: AllRepositories, unique_user:
|
|||
for tag in created_tags:
|
||||
assert tag.id in tag_ids
|
||||
|
||||
# Test random ordering with tag filter
|
||||
pagination_query = PaginationQuery(
|
||||
page=1,
|
||||
per_page=-1,
|
||||
order_by="random",
|
||||
pagination_seed=str(datetime.now()),
|
||||
order_direction=OrderDirection.asc,
|
||||
)
|
||||
random_ordered = []
|
||||
for i in range(5):
|
||||
pagination_query.pagination_seed = str(datetime.now())
|
||||
random_ordered.append(database.recipes.page_all(pagination_query, tags=[tag_slug]).items)
|
||||
assert len(random_ordered[0]) == 15
|
||||
assert not all(i == random_ordered[0] for i in random_ordered)
|
||||
|
||||
|
||||
def test_recipe_repo_pagination_by_tools(database: AllRepositories, unique_user: TestUser):
|
||||
slug1, slug2 = (random_string(10) for _ in range(2))
|
||||
|
@ -360,6 +390,21 @@ def test_recipe_repo_pagination_by_tools(database: AllRepositories, unique_user:
|
|||
for tool in created_tools:
|
||||
assert tool.id in tool_ids
|
||||
|
||||
# Test random ordering with tools filter
|
||||
pagination_query = PaginationQuery(
|
||||
page=1,
|
||||
per_page=-1,
|
||||
order_by="random",
|
||||
pagination_seed=str(datetime.now()),
|
||||
order_direction=OrderDirection.asc,
|
||||
)
|
||||
random_ordered = []
|
||||
for i in range(5):
|
||||
pagination_query.pagination_seed = str(datetime.now())
|
||||
random_ordered.append(database.recipes.page_all(pagination_query, tools=[tool_id]).items)
|
||||
assert len(random_ordered[0]) == 15
|
||||
assert not all(i == random_ordered[0] for i in random_ordered)
|
||||
|
||||
|
||||
def test_recipe_repo_pagination_by_foods(database: AllRepositories, unique_user: TestUser):
|
||||
slug1, slug2 = (random_string(10) for _ in range(2))
|
||||
|
@ -430,6 +475,20 @@ def test_recipe_repo_pagination_by_foods(database: AllRepositories, unique_user:
|
|||
|
||||
assert len(recipes_with_either_food) == 20
|
||||
|
||||
pagination_query = PaginationQuery(
|
||||
page=1,
|
||||
per_page=-1,
|
||||
order_by="random",
|
||||
pagination_seed=str(datetime.now()),
|
||||
order_direction=OrderDirection.asc,
|
||||
)
|
||||
random_ordered = []
|
||||
for i in range(5):
|
||||
pagination_query.pagination_seed = str(datetime.now())
|
||||
random_ordered.append(database.recipes.page_all(pagination_query, foods=[food_id]).items)
|
||||
assert len(random_ordered[0]) == 15
|
||||
assert not all(i == random_ordered[0] for i in random_ordered)
|
||||
|
||||
|
||||
def test_recipe_repo_search(database: AllRepositories, unique_user: TestUser):
|
||||
recipes = [
|
||||
|
@ -461,6 +520,37 @@ def test_recipe_repo_search(database: AllRepositories, unique_user: TestUser):
|
|||
group_id=unique_user.group_id,
|
||||
name="Rátàtôuile",
|
||||
),
|
||||
# Add a bunch of recipes for stable randomization
|
||||
Recipe(
|
||||
user_id=unique_user.user_id,
|
||||
group_id=unique_user.group_id,
|
||||
name=f"{random_string(10)} soup",
|
||||
),
|
||||
Recipe(
|
||||
user_id=unique_user.user_id,
|
||||
group_id=unique_user.group_id,
|
||||
name=f"{random_string(10)} soup",
|
||||
),
|
||||
Recipe(
|
||||
user_id=unique_user.user_id,
|
||||
group_id=unique_user.group_id,
|
||||
name=f"{random_string(10)} soup",
|
||||
),
|
||||
Recipe(
|
||||
user_id=unique_user.user_id,
|
||||
group_id=unique_user.group_id,
|
||||
name=f"{random_string(10)} soup",
|
||||
),
|
||||
Recipe(
|
||||
user_id=unique_user.user_id,
|
||||
group_id=unique_user.group_id,
|
||||
name=f"{random_string(10)} soup",
|
||||
),
|
||||
Recipe(
|
||||
user_id=unique_user.user_id,
|
||||
group_id=unique_user.group_id,
|
||||
name=f"{random_string(10)} soup",
|
||||
),
|
||||
]
|
||||
|
||||
for recipe in recipes:
|
||||
|
@ -520,3 +610,17 @@ def test_recipe_repo_search(database: AllRepositories, unique_user: TestUser):
|
|||
fuzzy_result = database.recipes.page_all(pagination_query, search="Steinbuck").items
|
||||
assert len(fuzzy_result) == 1
|
||||
assert fuzzy_result[0].name == "Steinbock Sloop"
|
||||
|
||||
# Test random ordering with search
|
||||
pagination_query = PaginationQuery(
|
||||
page=1,
|
||||
per_page=-1,
|
||||
order_by="random",
|
||||
pagination_seed=str(datetime.now()),
|
||||
order_direction=OrderDirection.asc,
|
||||
)
|
||||
random_ordered = []
|
||||
for i in range(5):
|
||||
pagination_query.pagination_seed = str(datetime.now())
|
||||
random_ordered.append(database.recipes.page_all(pagination_query, search="soup").items)
|
||||
assert not all(i == random_ordered[0] for i in random_ordered)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue